Does WTL CWindowImpl compatible with CWnd? - sdl-2

i have simple video player.
https://github.com/sailfish009/sample_video
now i want to port it to windows template library 9.1.
Edit: solved, CWindowImpl's handler compatible with CWnd's.
//screen = SDL_CreateWindowFrom(this->m_hWnd); //HWND from CWnd previous working code
screen = SDL_CreateWindowFrom(m_hWndClient); //HWND from CWindowImpl

The question is asked incorrectly. You don't look for compatibility, you just look for a way to access HWND window handle.
No, the classes are not compatible and more to that they are different conceptually. In ATL/WTL CWindowImpl is a class that implements a window procedure. Such procedure is typically a static function, and the helper class does the job of "attaching" it to C++ class, connects it to specific thin window wrapper such as CWindow, offers easy way to connect message handlers etc. m_hWndClient is not even a member of CWindowImpl and belongs to WTL frame window related classes.

Related

IFileOpenDialog Show method not using input parent HWND

I have a classic c++ desktop application that uses IFileOpenDialog. I was using Spy++ and noticed that although we call Show with the hWnd of a view, when the dialog shows up, Spy shows me the owner is not the view but rather our top level frame the view is a child of.
The IModalWindow::Show documentation only says the input is the handle of the owner window. I even stepped thru assembly code and verified the hWnd we used was pushed into a register and made it to the called frame.
I have not found any Microsoft documentation that indicates this behavior would occur. I'm not even sure how the system would find the top level parent other than to walk the parent chain until a parent/owner is returned that is the desktop and then using the window whose parent/owner was the desktop. Guess I could hook into GetParent and/or GetWindow to see if those calls are made when we call Show.
Does anyone know about this or see the same thing?

Does the window class name change in win32api

Does the window class name you specify in lpszClassName ever change? E. g. for applications like firefox? Or is that name always the same for an application? SO once I installed Firefox, I can be sure that its classname doesnt change?
Thanks!
The only way you can guarantee the class doesn't change is with some promise from the application developer. For example Winamp guaranteed its window class so you could use FindWindow on it for automation.
But there is nothing stopping an application from using a different class name for every window it ever creates.
Note that if you are trying to automate external applications, window class name is only one of countless moving-target problems. For example you get the window handle via FindWindow. You send it a WM_COMMAND for some command ID you found. Next version the application changes this command's ID. Same issue.

InvokeMethod of Windows Workflow 4 can encounter Exception C0000005

Thank you for reading at first.
I designed a WPF application which rehosted the Designer, Toolbox and Properties of Windows Workflow. My Idea is really simple that I just want have visualization at runtime about my workflow and design them in the runtime as well.
ISSUE:
Now I try to Invoke a Method of a class under the same namespace of whole application. The class is called MyTwsClass. Please have a look below:
It is extremely Simple. The TwsClass is from a Reference ActiveX of Interactive Brokers Trading Software. This ActiveX simply provide the method and event for you to communicate with your account. Alright, I implement the MyConnect() method as you can see and this method simply set up some string and int variables to be parameters of connect method from TwsClass. I noticed that I could not set MyTwsClass or MyConnect method as static.
Now, at runtime designer, I try to invoke the MyConnect method. First of all, picture below:
Since MyTwsClass could not be a static class with static method (I guess it is because it inherits from the ActiveX class TwsClass, I am not sure as a newbie.) So I wanna invoke the instance method. It has no complaints before running the workflow. After running this, I expect that I should be able to connect to the API of the trading software.
Now I run the workflow:
Right after clicking the running button, it runs and I got pop up window to tell me that APP has crashed with exception code C0000005. If I click the close option, my WPF application will be closed. BUT before I close it, I could see that ACTUALLY the crashed WPF actually connected to the API as you can see in picture above to tell me that 1 is connected......
I tried my best to check this problem on Internet. I am kind of have sense that it is all because of some issue within Interop or COM process between my WPF and the reference ActiveX as the crash window indicated that the TwsSocket.dll is the reason.
But I really could not figure out further.....

How can I get the name of a Visual Basic control given its HWND?

I'm working on a little macro record/replay tool which can automate a few very old Visual Basic 6 GUIs we have. To do so, I'm identifying the controls by their name (the value of the name property of a control, that is).
One part of this tool needs to determine the name of a control given its HWND. For newer Visual Basic applications which were done using VB.NET, I can use the WM_GETCONTROLNAME window message. This works nicely.
However, this message is not understood by older windows. Is there any way to do this for controls of Visual Basic 6 applications? A solution which does not require being in the process of the GUI would be preferrable, but if I had a solution which only works inside the GUI process then that would be acceptable as well (since I can do the injection myself).
UPDATE: One thing I just tried, this moderate success: I used the AccessibleObjectFromWindow to check for implementations of the IAccessible interface of the object which shows the given HWND. In case I get an implementation (it seems that many [all?] Visual Basic controls implement this interface), I use the accName property to read out the "accessible name". Sometimes this does yield a useful string, but usually it doesn't.
I believe the only way would be getting inside the process and obtaining a pointer to the Form object, yet I have no idea how to do it from outside.
Is it possible you add support for the WM_GETCONTROLNAME to those older applications?
Or maybe, you could identify the controls by some other, natively-available properties?
Other that that, as Raymond is saying, there isn't much you can do.
Can you modify the vb6 apps? if so in each form load event you could iterate me.controls and use the SetProp(ctrl.hwnd, "MYNAME:" & ctrl.name, 0) api to add the name to the window's own property list, then in your other app you can EnumProps(ctrl_HWND) looking for the one that begins with MYNAME: and parse out the value.

Subscribe to Vista Events in .NET (e.g. Window Opened)

I am trying to build my own little toolbox for Vista.
One of the features is a "window placeing tool" which places the windows at saved position. Another tool I could imagine are extensions to firefox or thunderbird...
For these tools to work, I need them to be able to capture "Events" in Vista.
To give you a concrete example:
Explorer Opened New Window
User started Firefox
Mouse moved
For the mouse case, there are some examples for C#.
I also know about the directory watcher, nice little helper.
Want I now need is the "new window opened event"
Any idea how to monitor this, without iterating the current window list every 5 seconds (I already know how to get Windows using the DLLImports, and getting Processes using managed code. But I have no Event when the explorer process opens a new windows)
Thanks for your help,
Chris
What you're talking about doing is not simple by any stretch.
You're going to need to register a hook, and you're going to have to build a callback procedure that gets called within another process's execution context -- this is not going to be .NET code (probably C instead), and will have to be in a DLL. That callback procedure will get called every time a certain class of events happens. It will examine the events it receives and filter out the ones you're interested, then send your application the notifications you want (probably via PostMessage). You'll then tap in to your application's main message loop to intercept those messages, and from there you can fire a .NET Event, or whatever you want.
Writing hook callbacks is tricky stuff because the code gets run within another process, not your own, and the memory management and concurrency issues take a bit of forethought. For that same reason, it's not going to be done in C#. Ideally, though, this callback code will be very small and very fast, since it's going to get called so often.
Also note that while perfectly "legal" in Win32, these system hooks have an immense amount of power and are commonly used by malware to change the way your system works. For that reason, you may run afoul of antivirus software if you attempt to do this sort of thing on a customer's computer.
Also note that the far-reaching effects of system hooks also means that simple programming mistakes can take down your whole system, which you will probably discover for yourself at some point while debugging; so save everything before you hit "run".
Good luck!
EDIT
Did a bit more search to see if there's any way to write the hook proc in C#, and came up with this:
How to set a Windows hook in Visual C# .NET
This is almost what you're looking for, but not quite. Hook procedures can either be global (which means that they run on every application) or thread (only runs within your application). The document states that:
Global hooks are not supported in the .NET Framework
Except for the
WH_KEYBOARD_LL low-level hook and the
WH_MOUSE_LL low-level hook, you cannot
implement global hooks in the
Microsoft .NET Framework. To install a
global hook, a hook must have a native
DLL export to inject itself in another
process that requires a valid,
consistent function to call into. This
behavior requires a DLL export. The
.NET Framework does not support DLL
exports. Managed code has no concept
of a consistent value for a function
pointer because these function
pointers are proxies that are built
dynamically.
Which means, again, to monitor things that go on outside your application's view, you need to set a global hook, which can't be written in .NET.
I have exactly the same issue as this, and I think I have a workable solution. Initially I looked into a similar option to the one mentioned by 'tylerl'. In my case however, instead of using 'SetWindowsHookEx', I attempted to use the similar function 'RegisterShellHookWindows'.
Unfortunately, this only succeeded in providing me with notifications of when a subset of windows are created/destroyed. The only windows which it provided notifications for are those shown on the taskbar.
Since I didn't fancy hacking into other processes, or writing the native code which would be required for SetWindowHookEx, I tried digging into the .NET automation APIs introduced in .NET 4.0, and I think this has the answer to your problem (at least as far as detecting when windows are opened / closed).
Here's a code snippet for using this API to detect windows being opened/closed:
using System.Windows.Automation;
private void StartMonitoringForWindowEvents()
{
Task.Factory.StartNew(() =>
{
AutomationEventHandler windowOpenedHandler = new AutomationEventHandler(OnWindowOpened);
System.Windows.Automation.Automation.AddAutomationEventHandler(
WindowPattern.WindowOpenedEvent, AutomationElement.RootElement,
TreeScope.Descendants, windowOpenedHandler);
});
}
private void OnWindowOpened(object source, AutomationEventArgs eventArgs)
{
try
{
AutomationElement sourceElement = (AutomationElement)source;
string message = string.Format(
"Automation.WindowOpened PID: {0}, Handle: {1}, Name:{2}",
sourceElement.Current.ProcessId,
sourceElement.Current.NativeWindowHandle,
sourceElement.Current.Name);
Debug.WriteLine(message);
// for each created window, register to watch for it being closed
RegisterForClosedWindowEvent(sourceElement);
}
catch
{
}
}
private void RegisterForClosedWindowEvent(AutomationElement element)
{
try
{
string elementName = element.Current.Name;
int processId = element.Current.ProcessId;
int nativeHandle = element.Current.NativeWindowHandle;
AutomationEventHandler windowClosedHandler = new AutomationEventHandler(
(ignoreSource, ignoreArgs) => OnWindowClosed(nativeHandle, processId, elementName));
System.Windows.Automation.Automation.AddAutomationEventHandler(
WindowPattern.WindowClosedEvent, element,
TreeScope.Element, windowClosedHandler);
}
catch
{
}
}
private void OnWindowClosed(int nativeHandle, int processId, string elementName)
{
string message = string.Format(
"Automation.WindowClosed PID: {0}, Handle: {1}, Name:{2}",
processId,
nativeHandle,
elementName);
Debug.WriteLine(message);
}
You will need to add a reference to the assemblies 'UIAutomationClient' and 'UIAutomationClientTypes'.
Here's a link to the MSDN documentation (you'll probably particularly want to take a look at the information on events):
http://msdn.microsoft.com/en-us/library/ms747327.aspx
Important implementation Notes:
1.) Notice that in the sample, I used a task factory to register for reception of the automation events. It's particularly important to avoid using the UI thread when registering for automation events or generally interacting with the automation APIs. Doing so can (and usually quickly does) result in a deadlock. Therefore, I use the task factory to ensure registration is done via the thread pool.
This also means, that the events will be received on the thread pool... So, if you need to perform any UI updates, you will have to marshal these across to the UI thread.
2.) You'll also note, that I capture any needed information on the element which may be closed, at the time of registration (using a closure). This is because, once the element is closed, we will no longer have access to this information - since the element has been destroyed.
Phil
The answer is not C# (or .Net) specific. You'll need to call SetWindowsHookEx( WH_CBT, ... ). This will allows to know when a window is created, destroyed, moved, sized, etc. You'll also need to get the relevant information from the window to identify if its one you need to do something about. Perhaps GetClassInfo, GetWindowLong, and GetWindowText.
The problem with the SetWindowsHookEx is that in order to get events from every window you need to have a separate win32 dll with the function in question exported. Although you might have success with the procedure outlined here.
To expand upon Joel Lucsy's answer, you need to use the Win32 API. However, there's a nice library, the Managed Windows API, that provides an object-oriented wrapper over common APIs. It may have what you need.

Resources