SendMessageCallback crushes - winapi

I am trying to sent keystrokes to a window that sometimes in background. Most of time it works good, but sometimes it just crushes. As I've noticed it happens when user presses same key on keyboard at exactly same time as the message is sent... Can you please give me some advice how to avoid those crushes?
Here is my code to call SendMessageCallback:
Native.SendAsyncProc del = new Native.SendAsyncProc(Helpers.Win32.Native.SendMessage_Callback);
Native.SendMessageCallback(MainWindowHandle, 256U, (int)System.Windows.Forms.Keys.D3, 0, del, UIntPtr.Zero);
Thread.Sleep(5);
Native.SendMessageCallback(MainWindowHandle, 257U, (int)System.Windows.Forms.Keys.D3, 0, del, UIntPtr.Zero);
and in Native:
[DllImport("user32.dll")]
public static extern bool SendMessageCallback(IntPtr hWnd, uint Msg, int
wParam, int lParam, SendAsyncProc lpCallback, UIntPtr dwData);
public delegate void SendAsyncProc(IntPtr hwnd, uint uMsg, UIntPtr dwData,
IntPtr lResult);
public static void SendMessage_Callback(IntPtr hwnd, uint uMsg, UIntPtr dwData, IntPtr lResult)
{
//LogManager.LogError("SM CB {0}",(DateTime.Now - td).TotalMilliseconds.ToString());
return;
}
Also Ive noticed it never raises SendMessage_Callback... But can not understand why till now...

Your problem is that you're trying to simulate keyboard input using the moral equivalent of PostMessage. That doesn't work reliably. In particular, apps in the background have lost focus and activation, and many applications rely on focus and activation messages to properly handle input. Raymond Chen has more about how Windows handles input here.
Also, you're not getting your callback because you're not pumping messages while your sleeping. Use a WaitHandle to wait, as it will pump messages while waiting. You'll need to set the event in your callback, of course.
So, if your code looked like this:
[DllImport("user32.dll")]
public static extern bool SendMessageCallback(IntPtr hWnd, uint Msg, int
wParam, int lParam, SendAsyncProc lpCallback, UIntPtr dwData);
public delegate void SendAsyncProc(IntPtr hwnd, uint uMsg, UIntPtr dwData,
IntPtr lResult);
WaitHandle waiter = new EventWaitHandle (false, EventResetMode.ManualReset);
public static void SendMessage_Callback(IntPtr hwnd, uint uMsg, UIntPtr dwData, IntPtr lResult)
{
waiter.Set();
return;
}
Native.SendAsyncProc del = Helpers.Win32.Native.SendMessage_Callback;
Native.SendMessageCallback(MainWindowHandle, 256U, (int)System.Windows.Forms.Keys.D3, 0, del, UIntPtr.Zero);
waiter.WaitOne();
Native.SendMessageCallback(MainWindowHandle, 257U, (int)System.Windows.Forms.Keys.D3, 0, del);
waiter.WaitOne();
You should at least get your callbacks. You'll need to rethink your keyboard simulation from scratch, though. Consider UI Automation, at a bare minimum.

Related

How can I get a message box to appear every time I left-click in a window?

I want to open a message box with the word "left" when I left click the mouse.
So I used wndproc and MK_LBUTTON, but the wndproc function wrote the code, but the WinMain part doesn't know how to write the code.
I don't want to open a window, but when I searched on Google, I only have a code example that only shows a window.
(Opening the window did not solve the problem ..)
What should I do? Help
(If you've written as much as possible but don't understand the question, please ask me and I'll answer it.
And I'm not good at English, so I wrote a translator.)
my code(try)
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance
, LPSTR lpszCmdParam, int nCmdShow)
{
//???
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
switch (iMessage) {
case MK_LBUTTON:
MessageBox(hWnd, TEXT("left"),TEXT("message"), MB_OK);
}
return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
MK_LBUTTON is not a message, you need to catch WM_LBUTTONDOWN, WM_LBUTTONUP or WM_LBUTTONDBLCLK.
These messages are only sent to the active window where the mouse is clicked. If you want to catch clicks on all windows then you need to use a mouse hook and pump messages.

Encapsulate Win32 in a class - pass class pointer in CreateWindow

I viewed many tutorials and posts on this subject, and they all say I pass the class instance pointer (this) in my CreateWindowEx() function, and then store it in the window procedure function, when the WM_NCCREATE message is sent. I guess this is because WM_NCCREATE is supposedly the first message that gets sent to the window procedure since a window is created.
A few questions/notes:
From debugging I came to know that actually WM_GETMINMAXINFO is the first sent message, before WM_NCCREATE (at least on my machine). Does this mean I should listen for this message instead of WM_NCCREATE?
According to this popular article, the reason everyone calls SetWindowLongPtr() after the message WM_NCCREATE is received is because
If the value does not exist by the time WM_NCCREATE is called then,
by some mysterious Windows behavior that I still don't understand, the
value never gets inserted.
I tried to do exactly that (that is, call SetWindowLongPtr() after CreateWindowEx()). It turns out to be just fine. The application runs okay. Below is my code, please tell me if there's something wrong with this approach.
void GLWin32::CreateWindow(...)
{
...
_hwnd = CreateWindowEx(NULL, _wndclassex.lpszClassName, title.c_str(), WS_OVERLAPPEDWINDOW, x, y, width, height, NULL, NULL, _hinstance, NULL);
SetWindowLongPtr(_hwnd, GWL_USERDATA, reinterpret_cast<LONG_PTR>(this));
...
}
//static window procedure for all instances of this class
LRESULT CALLBACK GLWin32::_msgRouter(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
LONG l = GetWindowLongPtr(hwnd, GWLP_USERDATA);
GLWin32* thisPtr = reinterpret_cast<GLWin32*>(l);
if (thisPtr)
return thisPtr->_winProc(msg, wparam, lparam);
else
return DefWindowProc(hwnd, msg, wparam, lparam);
}
LRESULT GLWin32::_winProc(UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case WM_CLOSE:
{
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(_hwnd, msg, wparam, lparam);
}
Why is my approach not used instead of the popular approach?
The problem with this approach is that if you want to use the instance when processing any of the window creation messages (including "ordinary" messages that are sent as part of the creation process), you won't have access to it.
Suppose you want to create a button when processing WM_CREATE (typical scenario) and you want to set the button text to some instance member value. You want something like:
LRESULT GLWin32::_winProc(UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case WM_CREATE:
{
CreateWindow("BUTTON", this->buttonText, WS_VISIBLE | WS_CHILD,
10, 10, 50, 30, this->hwnd, NULL, this->hInstance, NULL);
return 0;
}
}
return DefWindowProc(_hwnd, msg, wparam, lparam);
}
Problem is, when WM_CREATE is processed (before CreateWindowEx returns), SetWindowLongPtr wasn't called yet and the instance pointer is missing, so _winProc isn't being called at all.

Atl CDialogImpl not showing on DoModal if called from static library

I wrote a super simple ATL dialog inside a project. Even when I noted that every example on the web implemented the CDialogImpl class inline (that is, the class definition and it's implmentation where in the definition itself) I wrote it normally, separating my definition in a .h file and implementation in a .cpp file. This class is summarized below:
CMainDialog.hpp
class CMainDialog: public CDialogImpl<CMainDialog>
{
public:
enum { IDD = IDD_MYDIALOGS_DIALOG};
BEGIN_MSG_MAP(CMainDialog)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
END_MSG_MAP()
CMainDialog();
~CMainDialog();
LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam,
BOOL& bHandled);
LRESULT OnCancel(UINT uMsg, WORD wID, HWND hWndCtl, BOOL& bHandled);
}
CMainDialog.cpp
CMainDialog::CMainDialog()
{
}
CMainDialog::~CMainDialog()
{
}
LRESULT CMainDialog::OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam,
BOOL& bHandled)
{
}
LRESULT CMainDialog::OnCancel(UINT uMsg, WORD wID, HWND hWndCtl,
BOOL& bHandled)
{
}
If I call this class from the same project, everything goes fine. The dialog shows. Example:
Calling DoModal
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
CMainDialog dialog;
dialog.DoModal();
return 0;
}
So I converted this project from .exe to static library and removed _tWinMain.
So, if I create a new ATL project, reference my newly created library and call CMainDialog.DoModal ... well, nothing happens. The constructor does get called, but the messages never start dispatching and the program ends inmediatly. Maybe I'm missing something?
I'm totally new to Win32 programming (although definitely not new to c++) so any help would be appreciated.
A static library does not have resources associated with it. Most likely the dialog code is trying to load the dialog template from the program resources but can't find it.

How to use DialogBox in Windows API

I'm learning windows api for some weeks, now I got a problem, my code is like this
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){
switch(message){
case(...)
DialogBox(hInstance,MAKEINTRESOURCE(IDD_MYDIALOG),hwnd,(DLGPROC)MyDialogProc);
return 0;
}
bool MyDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){
switch (message){
...
}
return false;
}
I don't know what else should I do before I use DialogBox where should I place EndDialog(). IDD_MYDIALOG is a resource file created by myself. I don't understand what is hInstance and how to get it, I think I just need a simple example, than I can know how use DialogBox. Thank you for helping!

Zombie Process after using a Windows subclass callback

I'm using the SetWindowSubclass(...) method of the Windows API to kind of "hook" messages transmitted to a WinProc that is out of the scope of my application.
My application is made of a core and plugins in DLL.
I've implemented such a Subclass in one of my plugins DLL.
I set the Subclass like this:
class MyPlugin
{
private:
static HWND s_OgrehWnd;
UINT_PTR m_uIdSubclass; //The ID of the Subclass WinProc
DWORD_PTR m_pdwRefData;
//....
public:
void MyPlugin::init();
LRESULT CALLBACK MyPlugin::windowProcSubclass(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
void MyPlugin::shutdown();
//....
};
//Set the subclass
void MyPlugin::init()
{
//...
bool resultsc = SetWindowSubclass(
s_hWnd,
MultitouchPlugin::windowProcSubclass,
m_uIdSubclass,
m_pdwRefData
);
//...
}
//The subclass
LRESULT CALLBACK MyPlugin::windowProcSubclass(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
switch(message)
{
case WM_GESTURE:
return MultitouchPlugin::g_cGestureEngine.WndProc(hWnd,wParam,lParam);
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
//Remove the subclass
void MyPlugin::shutdown()
{
//shutdown called - unregister stuff here
bool isSublcassed = GetWindowSubclass(s_hWnd, MultitouchPlugin::windowProcSubclass, m_uIdSubclass, &m_pdwRefData);
if(isSublcassed)
{
RemoveWindowSubclass(s_OgrehWnd, MultitouchPlugin::windowProcSubclass, m_uIdSubclass);
}
}
My problem is that when I quit the application, I can see the process that keeps running on in the 'Windows Task Manager' tool.
In debug mode, i've checked that it goes calls RemoveWindowSubclass(), and it does it.
If I remove my plugin with this code, there is no zombie process....
Does somebody has an idea about a solution to this problem?
Thanx in advance for the help

Resources