Some object/pointer questions.

coldfusion244

Junior Contributor
Joined
Nov 24, 2004
Messages
266
Location
Philadelphia
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.
 
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.
 
here is the code:

C#:
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];
		}
	}
}
 
Last edited by a moderator:
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]
 
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#.
 
* 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.

Code:
[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();
 
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.
 
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#.
 
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 ;)
 
Back
Top