In a WPF app of mine, I have to let the user choose a certificate. I do this via the X509Certificate2UI.SelectFromCollection-method. For proper dialog handling, the SelectFromCollection-method needs an IntPtr of the parents Hwnd. I have found the following code to provide this:
HwndSource source = (HwndSource)HwndSource.FromVisual(Window.GetWindow(this));
var certificates= X509Certificate2UI.SelectFromCollection(...,source.Handle);
So far, this works fine. My question is, because I have no big knowledge of Win32 or interop, if I have to do some cleanup code after this, or if there are some pitfalls in using the HwndSource-class like I did above?
I have seen that HwndSource implements IDisposable, but disposing the object after use closes the parent window. Therefore this seems not to be the intended usage.
WPF window is made up of two parts:
Window area which is made up of Operating System Window
Non - Window area which is inside a WPF window
Now, a WPF window being a ContentControl holds everything as its Content. So you can say every pixel of the Content inside the Window class is held by the Outside window. Every Visual of WPF does not have its own HANDLE associated with it, rather it is a content for the outside window element.
For detail refer to this - http://www.abhisheksur.com/2010/12/win32-handle-hwnd-wpf-objects-note.html
So, when you are disposing that handle, you are actually disposing your main window handler which results in close of complete application.
Hence, you are here only fetching your window handler and not creating anything which you might need to dispose..!!
Related
I'm using SDL2 (specifically, a C# wrapper of SDL2 (SDL2-CS) but it has all the same features and functionality) and am trying to make a game editor with it. Everything's going really well, but there's one piece of functionality I'd really like. That's to make one specific window always appear on top of its parent window, while making the parent window inaccessible. When the window is minimized and you open it, it opens and focuses on the child window. When you try to access the parent window, it flickers and you hear a windows error message.
I know how to manually focus on a window, but I don't know how to make a sort of "link" like that between two windows, where window A is inaccessible until window B is closed.
I know the Windows Forms equivalent is Form.ShowDialog(). That's what I want, but currently the way it works is like Form.Show(). To clarify, I'm not using Windows Forms or any other library/framework. I'm using pure SDL2; this was just an example.
I'm looking to implement this using pure SDL2.
I have developed a dll which is loaded from a thirdparty application.
The application does not provide me any events like WM_SIZE, WM_MOVE etc.
My dll displays a window (dialog) which is child of the main application.
I want that my window should move whenever main application is resized or moved.
How can I achieve this? As I said, the main application does not provide any WM_SIZE or WM_MOVE events.
Is there a way to subscribe to events of the application using the application handle?
OR can a child window know when main application is moved or resized without these events?
If a window has a style WS_CHILD it never receives a WM_MOVE or WM_SIZE message when the parent moves!
Why should it? Its position (relative to the parent) and its size doesn't change. Also the OS Windows takes care about any repainting that has to occur by uncovering sections of the window.
So when you are saying that the window should move with the parent and it doesn't than the window isn't a child of the parent. (Style WS_CHILD). Recheck this with Spy++. Or maybe you have only an owned window. (Your question isn't detailed enough).
If you have a non WS_CHILD window and you want it to move with another window, you can use a timer to recheck if the other window moved. Or if the window is in the same process you can subclass the window and post your own message to your window when the parent receives WM_SIZE/WM_MOVE.
I have an interesting case to solve:
I have a native (winapi) application, which uses MDI. This application allows me to extend itself with a simple scripting language. The scripts are launched on different thread than UI thread (although I can get the UI thread ID with appropriate functions). The scripting language also allow me to launch any c++ code (through LoadLibrary).
What I would like to achieve is to create a new window inside this application, which could host WPF and "attach it" as a MDI child window to MDI client (mdi area). Also, I would like this window to properly "talk" to MDI area, for example update list of windows in mdi menu.
So far, my first guess was to just create a WinForms window, host WPF inside, and then try to make it mdi child window by setting MDI client as it's parent (because my hosting application is not written in c#, I only have a handle, so I did this with User32.SetParent() P/Invoke). This worked almost well, after I attached my script thread to GUI thread, but I had few problems with it: the MDI menu with active windows did not update, the window did not interact correctly (it stayed on stop when it shouldn't etc.).
Then, I tried to set flags (style, exStyles) with SetWindowLongPtr. It changed my window's behavior a bit, but that was still not it.
Now I'm considering using CreateMDIWindow function, or doing it by SendMessage, according to docs sending message should create a window, even if I send it from different thread. The problem is, that this way would give me a native handle only, and I could not find (yet) any way of hosting WinForms / WPF inside it.
I'm curious if anyone tried to do something similar and had any results with it? Which way would be the best - trying to create a WinForms window and add it to MDI client, or create a native window and try to host WinForms in it (any particular way of doing that)?
Most answers for this question I have found are dealing with situation where hosting application is managed, so you can just set .MDIParent property, which won't work in this case I'm afraid.
in winForms, I have .Handle property, how do I get the equivalent to in WPF?
I tried using WindowInteropHelper but it does not suporte RichTextBox,only Window types.
Thanks in advance.
Controls in WPF do not have associated WinAPI handle, like WinForms control do. WPF uses only one WinAPI window to process window messages from OS and encapsulates it in Window class instance. The best you can do is to navigate through parents of your control until you find a Window and get the handle. As far as I understand this will likely be the same handle as one returned by WindowInteropHeler.
UPD.
To make this answer more useful and out-of-box'y here is some code (not tested though):
IntPtr hwnd = new WindowInteropHelper(Window.GetWindow(userControlRefernce)).Handle;
RichTextBox does not have HWND handle in WPF. You can still use a RichTextBox from WinForms library using WindowsFormsIntegration assembly, if you really need this handle.
Remember that you can always check what elements have or do not have handles using Spy++ utility.
I have a legacy app written in C that consists of a main window and several mdi children opened from menu options. To allow new mdi children to be written in C# I have created a C++ COM interop layer that is called by the C code and in turn calls the C# code. I then use the SetParent API to set the C main window as the new parent of any C# window opened. This seems to work - the C# window behaves like an MDI child of the main window. BUT, the child window does not paint properly and only gets worse if you move other windows over it or move it to the edges of the main window - it gets painted with parts of the other windows or leaves bits of itself lying around as it moves. In addition the screen doesn't respond very well eg you cannot tab from one textbox to another.
Please don't question the architecture of my solution (believe me, this is the only way), but if you've ever seen a problem like this with a child created by SetParent I'd love to hear if you managed to fix it.
Try these things:
Add Application.DoEvents inside a processing loop that is normally running when things go bad.
Try refreshing the MDI forms from within the main form's paint event.
I don't totally understand how SetParent() works; that being said, here's some more things to consider:
In the MSDN community content of the SetParent documentation, Chango V. from Microsoft added that you: "need to call SetWindowPos(SWP_FRAMECHANGED) when changing between null and non-null parent."
Also, are you sure you are actually running the .NET Form message loop? Did you call Application.Run(yourManagedForm), or are you running your own message loop in the C code? If you're running your own message loop, you may need to forward messages to the WndProc method on your managed form after filtering it through PreProcessMessage. You would need to expose an interface to these as they are protected. I don't know how valid this is, though.