coldfusion244 Posted November 24, 2004 Posted November 24, 2004 I am making the transition from vc++ to c#, and i'm having some problems with objects and pointers. I have a class that scans the system for certain windows, if it finds one, it creates a new object of a class that I created. This works great, except for when I need to access them again. I tried using a derived collection class, but it seems that once put into the collection class it calls upon the objects destructor. This is bad, since I am checking those windows for updating, as well as holding other window specific data. So I turned to pointers (which in C# I am unfamiliar with). What I decided to do was have a collection of type IntPtr (derived) and just pass it handles to my objects in memory as it would ideally be faster. However I can not create a pointer of a user defined type, at least I searched MSDN all over and found only primitives. If someone has a better idea or can help me with customer object pointers that would be greatly appreciated :) . Be honest, if I should just stick with VC++ then tell me :rolleyes: this way I can start porting my code over, thanks guys. Quote -Sean
Administrators PlausiblyDamp Posted November 24, 2004 Administrators Posted November 24, 2004 Any chance you could post your existing code (or at least the bits you are having problems with). Also when you say it calls the object's destructor when you put them into a collection; could you post the collection class / object code as that sounds very unusual behavior. Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
coldfusion244 Posted November 24, 2004 Author Posted November 24, 2004 (edited) here is the code: using System; namespace cWindows { /// <summary> /// clsCollection is the derrived collection class /// for holding all of the handles for all Correct open windows. /// </summary> public class clsCollection:System.Collections.CollectionBase { public void Add(clsWin aWin) { List.Add(aWin); } public void Remove(int index) { if (index > Count-1 || index <0 ) { } else { List.RemoveAt(index); } } public void Remove(clsWin aWin) { int counter; IntPtr dWin = IntPtr.Zero; for(counter = 0; counter <= Count - 1; counter++) { dWin = Item(counter).m_hWnd; if (dWin == aWin.m_hWnd) { Remove(counter); } } } public clsWin Item(int index) { return (clsWin) List[index]; } } } Edited November 25, 2004 by PlausiblyDamp Quote -Sean
coldfusion244 Posted November 24, 2004 Author Posted November 24, 2004 Sorry for the sloppy code posting, I tried using the Code tags and IE crashed on me everytime! Quote -Sean
Administrators PlausiblyDamp Posted November 25, 2004 Administrators Posted November 25, 2004 Can't see anything that would cause the dispose method to be called in there, could you post the clsWin code as well. Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
coldfusion244 Posted November 25, 2004 Author Posted November 25, 2004 The clsWin code is huge, a few hundred lines of code. I think though the error lies somewhere in my clsEnum. I use this to enumerate all of the open windows to find the ones I want. I'll post it here: [CS] using System; using System.Runtime.InteropServices; using System.Text; namespace cAIM { /// <summary> /// Enumerates all instances of Windows and ands them to an instianted /// clsCollection class. Must set Collections before using. /// </summary> public class clsEnum { public static clsCollection m_cCollection; [DllImport("user32.dll")] private static extern int EnumWindows(EnumWindowsProc ewp, int lParam); [DllImport("user32.dll", CharSet=CharSet.Auto)] private static extern int GetWindowText(IntPtr hWnd, StringBuilder ClassName, int nMaxCount); [DllImport("User32.Dll", CharSet=CharSet.Auto)] private static extern void GetClassName(IntPtr h, StringBuilder s, int nMaxCount); private delegate bool EnumWindowsProc(IntPtr hwnd, int lParam); public clsEnum() { } public void StartEnum() { EnumWindowsProc callbackProc = new EnumWindowsProc(EnumWin); EnumWindows(callbackProc,0); callbackProc = null; ForceUpdate();//Force to check for validity } public void Setup(clsCollection cCollection) { m_cCollection = cCollection; } private static bool EnumWin(IntPtr Hwnd, int lParam) { string tcl = "WindowClass"; string gcl = GetClass(Hwnd); string strWin = WindowText(Hwnd); if (gcl == tcl) { if (strWin == "caption") { } else { AddWin(Hwnd); } } return true; } private static string WindowText(IntPtr Hwnd) { StringBuilder mtitle = new StringBuilder(256); IntPtr mywin = Hwnd; GetWindowText(mywin,mtitle,256); return mtitle.ToString(); } private static string GetClass(IntPtr Hwnd) { StringBuilder mclass = new StringBuilder(256); GetClassName(Hwnd,mclass,256); return mclass.ToString(); } private static void AddWin(IntPtr hWnd) { clsWin nWin = new clsWin(hWnd); int counter = 0; bool bflag = false; for(counter = 0; counter < m_cCollection.Count; counter++) { if (m_cCollection.Item(counter).m_hWnd == hWnd) { bflag = true; nWin = m_cCollection.Item(counter); break; } } if (bflag == true) { //do nothing it's in there, it will be force updated } else { m_cCollection.Add(nWin); } nWin = null; } private void ForceUpdate() { int counter = 0; bool btest = false; for(counter = 0; counter < m_cCollection.Count; counter++) { btest = false; btest = m_cCollection.Item(counter).Update(); if (btest == false) { m_cCollection.Remove(counter); } } } }//end class }//end namespace [/CS] Quote -Sean
HJB417 Posted November 26, 2004 Posted November 26, 2004 I think you're going to have to post reproduceable code for this one. Quote
coldfusion244 Posted November 26, 2004 Author Posted November 26, 2004 Ok, I think what's going on is that I'm creating a new object everytime I add it to the collection. So in essence I believe I am making 2 objects for every 1 that I actually have. I think the program is confusing the objects that it has. Ok, new question then. How could I put an object (onto the heap I presume) in memory so that C#'s garbage collector doesn't touch it, but this way I could add it's memory location to the collection. Then I want to go through the collection and use a pointer(s) to use the methods in my objects in memory. I don't know if that makes sense. I guess what I am asking is, how would I just put all my new clsWin's in memory and access then with pointers. in C++ I could say clsWin MyCreatedObject = new clsWin(Hwnd); clsWin* pclsWin = &MyCreatedObject; pclsWin->MyMtehod(); But I can't do that in C# or can I. I might just be confusing myself :confused: C# kept complaining to me that it could use pointers with primitives. I'm so confused with C#. Quote -Sean
HJB417 Posted November 26, 2004 Posted November 26, 2004 * all objects that do not derive from System.ValueType live on the heap. * Drop the notion of pointers. C++ introduced references, which is what is used in c# to access objects on the heap. * Think of System.Object as void*, anything can be (up)casted to it, and unlike c++, when you upcast, it preserves the object. * For an object to be garbage collected, there must be no strong references to it. [c++] clsWin MyCreatedObject = clsWin(Hwnd); clsWin *pclsWin = &MyCreatedObject; pclsWin->MyMtehod(); [c++] clsWin *MyCreatedObject = new clsWin(Hwnd); clsWin *pclsWin = MyCreatedObject; pclsWin->MyMtehod(); [c++] clsWin *MyCreatedObject = new clsWin(Hwnd); clsWin &pclsWin = *MyCreatedObject; pclsWin.MyMtehod(); [c#] clsWin MyCreatedObject = new clsWin(Hwnd); clsWin pclsWin = MyCreatedObject; pclsWin.MyMtehod(); Quote
coldfusion244 Posted November 26, 2004 Author Posted November 26, 2004 wow, thanks HJB! I guess my last question then, would be (unless I didn't totally understand you HJB) how I could access objects from their memory location. Since my problem is that I'm creating a new clsWin everytime I add it to the collection class, I was thinking that I should just use memory locations to access them. Store the memory locations in the collections and use a regular object. I don't think this will work but something to the effect of: [CS] clsWin MyWin = new clsWin(); //default object MyWin = m_cColletion.Address(hWnd); //set object = object in memory [/CS] Where Address would return a reference to the memory location. Then when I added items to the colleciton I would ad their memory reference as the value and their hWnd as the key. Quote -Sean
HJB417 Posted November 26, 2004 Posted November 26, 2004 I think you should rephrase your question. Dont say "memory location" and "memory reference". You can use pointers in c# by writing unsafe code. There is c++.net (managed c++). I think maybe you should write your app in this 1) it's c++ 2) It's more explicit, and it will make you a better .net programmer because you'll know what those c# keywords really do in the background. e..x: as, is, locked, etc. 3) It will be a better transition to .net for you than using c#. Quote
coldfusion244 Posted November 26, 2004 Author Posted November 26, 2004 I guess that's what I'll do. Thanks for all the help guys! I guess the transistion from C++ to .net is going to be harder than I thought. :( :o Special thanks for putting up with my unique stupidity ;) Quote -Sean
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.