Essentially I'm inside a process' memory via an injected DLL and I want to stop window creation. I've tried hooking the following:
CreateWindowExW
CreateDialogParamW
DialogBoxParamW
Unfortunately, the creation of the window I want to destroy is not triggering any of my hooks. There are several IE controls within the aforementioned window and the CreateWindowExW calls are being hit for them; but not the actual window I want. It's a simple popup box, and does show up in Spy++/Window Hack so I'm certain it's an actual window.
Any ideas?
You need to try all the possible variations of the functions you are trying to hook CreateWindowExA, CreateWindowW, CreateWindowA, etc. They aren't necessarily just wrappers around the main *W one.
Related
I'm using and improving on an open source MFC work-alike library called FFC. Sometimes the library associates the wrong window handle to a dialog object, which means the C++ object can't be found later when the correct handle is looked up. In particular, this is happening when the application opens its root window, which is a dialog that it opens with a call to DoModal.
In its DoModal function, the FFC library uses a... "surprising" way to attach the handle to the dialog object. It stashes the "this" pointer in a global variable and hooks a function to be called on all window messages before calling the DialogBox function. This hook function it registered in term assumes the handle from the first message it receives is the handle for the window in the global variable, and attaches that handle to it.
Sometimes, this works. Often - and I don't know if it's because of intrusive things done by the McAfee scanner on my work computer, or because my program starts from a console window, or something else - many unrelated messages will be captured before a message actually meant for the modal dialog comes through.
At first I thought it was because FFC wasn't making sure the message it looks for is "WM_CREATE". I added this check, but it didn't fix the problem. Turns out one or more of the spurious messages are also WM_CREATE messages! Before it gets the one for the real dialog, the first WM_CREATE it receives is a handle for a window with blank window text and rectangle 0,0-0,0.
So is this really the correct or canonical way to get the handle for a modal dialog? It seems unreliable. (Note that because the dialog is modal, you can't use the return value from CreateWindowEx because the DialogBox function doesn't return until the modal dialog is closed.) Is this really how MFC does it? Is there a better way? Could I associate some data with the dialog or look for data that should be associated with it to make sure I have the right window handle? (For instance checking the template parameter passed to the dialog box call, if I can get that back from the handle somehow.)
I am sure this is published in books, but MFC sets a windows hook (WH_CBT) and then looks for the HCBT_CREATEWND code in the hook to marry the C++ object to the HWND.
I have a Qt based console application, that has to be located on the Windows System Tray (aka Notification Area).
The question: how can I hide the console window instead of minimizing it if the user clicks on "minimize" icon? I know the ShowWindow method, but as I guess, I have to call it asynchronously.
You need to obtain the HWND window handle of the Console window, then you can use ShowWindow to show or hide it in the usual way.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms683175(v=vs.85).aspx
The question is when do you do this? You need to know when the window is minimised in order to know whether to hide it.
You could check this periodically, but you should be careful to ensure you are not preventing laptops etc. from sleeping by doing so.
Alternatively you could install a message hook, or subclass the window, to recieve immediate notifications.
Subclassing the window is probably the best method.
This happens with all ActiveX controls. If I reposition an ActiveX control with DeferWindowPos
HDWP hdwp = BeginDeferWindowPos(1);
DeferWindowPos(hdwp, m_pActiveX->GetSafeHwnd(), NULL, left, top, width, height, SWP_NOZORDER);
EndDeferWindowPos(hdwp);
it goes there but then moves/resizes to its old rectangle once you click anywhere inside the control. If I use MoveWindow instead
m_pActiveX->MoveWindow(left, top, width, height);
this doesn't happen.
It doesn't happen with any other type of control, only with ActiveX controls, but it happens with all of them. I made a test to confirm this, creating a new ActiveX control project and didn't make any changes, and the problem was still there.
You never got an appropriate answer. I'll try to help out a bit here.
The issue is that MFC hides a lot of the trickiness with hosting an ActiveX control within it's framework. Specifically, if you step into the MoveWindow call, it is not simply a wrapper around the Win32 MoveWindow function. It calls into the OLE Control Container support classes. This basically says, if we have a control site interface, then call COleControlSite::MoveWindow, otherwise call the standard Win32 MoveWindow. The same occurs with several other window functions handled by CWnd etc. For example COleControlSite::SetWindowPos handles hiding/showing the control, then calls COleControlSite::MoveWindow to move it, and then finally calls ::SetWindowPos (with the move/show flags masked out) to handle the rest.
Once within COleControlSite::MoveWindow, you will notice it does several things: it calls SetExtent, updates it's internal m_rect member, and then calls SetObjectRects.
Bypassing these for ActiveX controls using the Win32 API directly (eg via DeferWindowPos) causes some of these crucial steps to be missed. Depending on how your code is layed out, usually you can handle this yourself.
What is this ActiveX control?
Apart from that consider that DeferWindowPos is meant for positioning multiple windows at the same time. The concept being you enter the begin statement, change a bunch of window positions for a new layout, then end to actually move and apply the new positions and sizes.
If you aren't updating multiple windows consider using SetWindowPos instead.
Consider also that you may be getting a message to move, resize, or change the windows position while you are deferring. To prevent this if that is what is happening pass the SWP_NOSENDCHANGING flag in each call to DeferWindowPos so that it is not sent or handle the message and clear all the bits in the WINDOWPOS struct received to prevent unwanted changes.
It is also possible for this call to fail ... are you checking the return value?
I am having trouble getting a global system hook to work. I want to be notified whenever a window is moving, as early as possible, and change the window size. This means the CBT hook HCBT_MOVESIZE won't cut it, it only happens after the window has been moved. I want to hook the actual movement of the window, and be able to change the window size during the move.
The hooks are set from a DLL, and the callback function is within that DLL. This is what I've tried.
WH_CALLWNDPROC. It does alert me when a window is moved (WM_MOVING is received for windows from other applications), but I cannot change the contents of the message.
WH_CALLWNDPROCRET Same as WH_CALLWNDPROC.
CBT hook HCBT_MOVESIZE. Event happens to late.
WH_GETMESSAGE. Never receive WM_MOVE, WM_MOVING or WM_WINDOWPOSCHANGING. This hook would allow me to change the messages.
Update: Windows event hooks seem to allow me to capture it:
hWinEventHook = SetWinEventHook(EVENT_SYSTEM_MOVESIZESTART,
EVENT_SYSTEM_MOVESIZEEND, NULL, WinEventProc,
0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
However, this creates a different problem: changing the size of the window using SetWindowPos() does not work (it changes size alright, but immediately changes back to its previous size), even though I use SWP_NOSENDCHANGING. Ideas?
Update 2: Subclassing seems to work, however Visual Studio crashes after each program run (so does a lot of other windows). It works well if I place breakpoints and walk through the "unsubclassing", but not when I let the program run by itself. Ideas?
I have a CBT hook (it was there from earlier), and whenever HCBT_ACTIVATE is sent for a new window, I remove any previous subclassing using SetWindowLongPtr() (this has to run on 64-bit as well), and then subclass the new window. If I put a breakpoint anywhere, and immediately resume the session when it breaks, everything works fine. However, when I do not have any breakpoints, Visual Studio crashes when the program exits.
Hm, I would've thought that HCBT_MOVESIZE is precisely what you want, given that the MSDN says this about CBT hooks:
The system calls this function before activating, creating, destroying,
minimizing, maximizing, moving, or sizing a window.
and in particular:
HCBT_MOVESIZE
A window is about to be moved or sized.
(these quotes were taken from http://msdn.microsoft.com/en-us/library/ms644977%28VS.85%29.aspx)
...so I'd have thought that you get the HCBT_MOVESIZE call in time. The hook function which handles HCBT_MOVESIZE is also allowed to return an integer so that the system can determine whether the operation is allowed or should be prevented. Hence, given that the HCBT_MOVESIZE hook should get an option to prevent the operation, I'd say it's called before the move event occurred.
Are you really sure the hook function is called after the move event? If you do a GetWindowRect call on the particular handle within your hook function, does the returned rect equal the rectangle which is passed to the hook function?
Hooks are pretty heavy. You only want to use them when you absolutely have to.
That said, you could use one of the basic hooks simply as a way to get into the process. Once in the process, you could subclass the window you're interested in and handle the sizing messages in your subclass proc rather than trying to catch everything at the hook level.
Depending on what you want to do in response to the resize, you might need some interprocess communication.
I'm creating a plugin framework, where my application loads a series of plugin DLL's, then creates a new window and pass this new window's handle to the plugin. The plugin can, then, use this handle to create their own GUI.
Everything seems to be working very well. The only problem is that when I press TAB on a plugin widget (An editbox, for example), it doen't jump to another widget. I figured out that some Windows messages are passed, and some others aren't. The WM_KEYDOWN is passed for other keys, because I can type on the editbox, but this message doesn't handle TAB key.
Hope somebody has a hint.
I'm using Borland VCL with CBuilder, but I think I could use any framework under WIN32 to create these plugins, since they never know how their parent windows were created.
It's very complex matter indeed.
When you hit TAB focus jumps to another control only when these controls belong to a Modal Dialog Box. In fact there are some buttons like ESC, LEFT, RIGHT, DOWN, UP, TAB which modal dialog message function treats in a special way. If you want these keys to behave in similar way with modeless dialog box or any other window you should change you message processing function and use IsDialogMessage inside. You'll find more information about IsDialogMessage function in MSDN also to better understand this stuff you may check as well Dialog Boxes section.
And, as was mentioned before, you should set WS_TABSTOP and WS_GROUP styles when needed.
Good luck!
I believe you'll have to take the following steps:
Subclass your edit controls (and other controls as needed).
Capture the WM_KEYDOWN message in your edit control's WndProc.
Check to see if the shift key is currently held down (using GetKeyState or similar).
Call GetWindow, passing in a handle to your edit control and either GW_HWNDPREV or GW_HWNDNEXT depending on whether shift is held down. This will give you the handle to the window that should receive focus.
Call SetFocus and pass in the window handle you got in step 4.
Make sure you handle the case where your edit controls are multiline, as you might want to have a real tab character appear instead of moving to the next control.
Hope that helps!
I believe you suffer from having a different instance of the VCL in each of your dlls and exes. Classes from the dll are not the same as the ones from your exe, even if they are called the same. Also global variables (Application, Screen) are not shared between them. Neither is the memory since they both have their own memory manager.
The solution is to have the dlls and the exe share the VCL library and the memory manager. I am not a BCB developer, but a Delphi developer. In Delphi we would just use the rtl and the vcl as runtime packages. Maybe you could do the BCB equivalent.
A DLL has its own TApplication object.
to provide uniform key handling. when the DLL Loads.
assign the DLL::TApplication to the EXE::TApplication
Be sure to do the reverse on exit.
--
Michael