|
If you know the class name of the window, you can use FindWindow to find the handle of the window in question, assuming you can interop that function in C#. Then pass that handle as the parent of the window you create.
Christian
I have drunk the cool-aid and found it wan and bitter. - Chris Maunder
|
|
|
|
|
Thanks Christian.
I actually know the window handle of the parent.
The problem ( I think ) is how do I convert a C++ window handle into something that I stuff into a C# form's parent property? Or is there a better way to solve this problem?
|
|
|
|
|
See my post[^] below. One way would be something like this (should only work in-proc, though):
Form f = (Form)Form.FromHandle(hWndParent); ...where hWndParent is an IntPtr that wraps the native HWND .
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
One important thing to understand is that the .NET Framework Class Library (FCL) pretty much encapsulates native APIs like those in Windows Management, Common Controls, GDI+, various COM libs, and more. A "C# window" (keep in mind that C# is just a language that uses the FCL and targets the CLR) is still tied to a Window resource, so it has an HWND (see the Handle property).
If you simply call Form.ShowDialog without any parameters (or with null ), the FCL uses the native GetActiveWindow API. If the would-be parent is active, then you don't need to do anything else. If you want to parent the Windows Form to a different parent, you need to use that would-be parent's HWND to get an instance of an IWin32Window . You should be able to use Control.FromHandle and pass the native HWND to get a Control reference, which implements IWin32Window . Pass that to ShowDialog then to re-parent it.
One other option you might consider is Managed C++. If you already have a good VC++ code base, Managed C++ might be a better way to go for an interim. Even without using the managed extensions, you can throw-on the /clr switch and have a managed (mixed mode, mostly native) application. If you added a few __gc class in there to encapsulate your native Windows, you would have a little more flexibility with interop'ing with C# since all languages targeting the CLR compile down to IL (unless they contain native instructions like a mixed mode MC++ assembly), so it doesn't matter what the source language of an assembly is.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Thanks Heath.
That's exactly what I was looking for.
|
|
|
|
|
Hello again Heath;
Could you have left out a step in your explanation?
Calling Form.FromHandle(myhwnd) returns null.
I have verified the CWnd.m_hWnd value passed by the C++ code in the debugger and also verified the validity of the passed hwnd by finding the window handle in Spy++. I have inspected the hwnd coming into the C# code as an IntPtr and see that it is the same as was passed from C++.
Any ideas?
|
|
|
|
|
Managed code can't communicate across application boundaries (for which a process is definitely one of them) so you might not be able to get the CLR to wrap an externally defined HWND , but this is all in the same process, right?
If that doesn't work, then you may be stuck with the parameterless ShowDialog implementation.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Very interesting idea! I personally have no idea off the top of my head (although Heath might), but my best guess would be you'd have to write a custom Designer class (or something else that implements IDesigner).
Let me look a bit more into it, and maybe I'll dig something up...
Jeremy Kimball
|
|
|
|
|
Nope, you're right. Some of the IDesigner implementations (like the ControlDesigner let you capture notification messages. See ControlDesigner.WndProc for more information.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
You extend ControlDesigner with your own designer class and override it.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
You don't. The designer host "hooks" your messages and routes them through the designer. Read about the ControlDesigner[^] in the .NET Framework SDK.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
|
|
I have a Hashtable. I need to go through it and delete some of the entries.
The problem it as soon as I delete an item the enumerator becomes invalid and the program crashes on enumerator.MoveNext. Do you know a way around this?
Here is the code:
<br />
IDictionaryEnumerator enumerator = table.GetEnumerator(); <br />
while (enumerator.MoveNext())<br />
{<br />
if (IsSubfolder(virtualFolder, enumerator.Key as String))<br />
{ <br />
table.Remove(virtualFolder); <br />
}<br />
}<br />
|
|
|
|
|
You could split it into two loops: One to mark those entries for deletion, then one to delete all marked keys...
Also, I'm not positive, but I believe a construct like this would work...
foreach( string key in table.Keys ) {
string value = (string)table[key];
if( ... ) {
}
}
Jeremy Kimball
|
|
|
|
|
No, foreach is a compiler "alias" that gets the enumerator and enumerates the collection (rather, the IEnumerable implementation). Doing that is the same as what he was doing originally.
Your first idea is one way of solving it, though.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
*sigh* yup, you're right...I said earlier, my brain is broke today
|
|
|
|
|
If you read the documentation for IEnumerator interface and its members, it is documented that an exception is thrown when you modify the underlying collection. This is by design for a reason. If you modify the collection that you're enumerating, there's a good chance that enumerated data was changed which makes your enumerator invalid. Note that the foreach keyword is nothing more than a compiler "alias" for getting the enumerator and looping through it much as you're doing.
One workaround is to clone the Hashtable (see Hashtable.Clone ) and enumerate it, removing the elements from the original. Since cloning the hashtable creates a shallow copy, the keys and values themselves will reference the same object (unless they are value types like int , long , DateTime , etc.).
You could also copy the keys to an array (using Hashtable.Keys.CopyTo ), enumerate that, and call Hashtable.Remove on the keys you want to remove. There's several other workarounds that would work along these lines as well.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
FYI, I saw a link to this[^] on MSDN. I haven't tried it myself, but it apparently allows you to modify a collection while in the foreach loop of that collection.
---------------------------
He who knows that enough is enough will always have enough.
-Lao Tsu
|
|
|
|
|
All this does is return a custom IEnumerator that doesn't keep track of the serial number (version of the enumerator). This is a very bad idea for reasons I mentioned earlier. If the collection over which you're enumerating changes, you should not continue enumerating because the underlying data has changed.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Interesting. Yeah like I said I hadn't actually looked at their code, thought I'd throw it out on the table anyway.
---------------------------
He who knows that enough is enough will always have enough.
-Lao Tsu
|
|
|
|
|
One way to do it is to have ArrayList that holds keys to be deleted.
ArrayList delteList = ...
foreach element in hashtable
if want to delete key
add key to deleteList
foreach key in deleteList
hashtable.delete(key)
|
|
|
|
|
Does anybody know how I could print a .Net Bitmap with Win32 Api calls? Thanks alot
|
|
|
|
|
Why would you want to? GDI+ (encapsulated in the System.Drawing classes) gives you all the functionality as GDI (though some things are still easier in GDI at times) and all the printing facilities in .NET allow you to manipulate the image that is printed (including text) however you want. It's a heck of a lot easier, especially since coordinate transformations are a little easier since the printer-specific coordinate mapping is abstracted away.
If you want to use Win32 printing APIs (which is really just GDI using the HDC of a printer), then find an example in C/C++ and go to all the work of P/Invoking what you need to do it in C#.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
The reason that I want to use API is because I am working on a project to print invoices. The .Net printing framework is to slow to keep up with the volume of invoices printed every night. So, my only other alternative is to print using the API. Thanks for your help.
|
|
|
|