MessageBox() returning 0 when called from Win32 button press - c++

I'm barely a week into Win32 GUI programming, so I'm confident/hopeful this is something simple. For your consideration, I've provided a sample of my code below.
As a quick brief, my application watches for another application to be open so that I can modify that application's memory. I've placed this initial check at the top of my UI looper as follows such that it will only run once (in which case the user can only cancel and the app closes, or execution resumes past the if statement with hWndApp having a value assigned):
if (!hWndApp) {
appCheck();
}
If I start my application and the other application isn't running, appCheck(); fires and the waterfall of execution therefrom acts accordingly: a message box appears (and will keep appearing if the user clicks "Retry") until the other application's window is found. If the user clicks "Cancel," the application exits and all is well. If they click "Retry" once the other application is running, then my application will finish painting to the screen and execution is normal.
The funny business starts the next time I call appCheck(); (which happens when one of either two buttons is clicked) if the other application has been opened, then closed.
While debugging (via Visual Studio 2017), the variable I assign the MessageBox() call to equals 0 when the other application has been opened, then closed, then the following:
Push button to call appCheck();
getProcessHandleAndPID(); is then called within the if statement because the window can't be found
AppCheckMessageBox(); is then called within the while loop because the window can't be found
The debugger then points to the first line inside of AppCheckMessageBox();, which is the entire int msgboxID = MessageBox(); bit
Pressing F11 (Step Into), no window shows and the application exists after the default choice in the switch statement is triggered since the value of msgboxID is 0 (indicating the MessageBox() call failed, so I tried calling GetLastError() before exit(EXIT_FAILURE), but to no avail).
I'm not sure where my error lies, but I've sought many solutions--none of which have panned out. Finally, if you see any variables below that look misnamed or undeclared, it's solely due to my modification of the code for this post to try to generalize/ shorten it. I may have left out some global variable declarations, etc.
Thank you for any help/guidance you can provide! I'm at my wit's end with this right now...lol.
//--------------------------------------------------
// Function to get process handle and PID of app /
//------------------------------------------------
void getProcessHandleAndPID()
{
hWndApp = FindWindow(NULL, _T("NameOfApplication"));
while (!hWndApp) {
AppCheckMessageBox();
}
//Much more code here
}
//---------------------------------
// Function to show message box /
//-------------------------------
int AppCheckMessageBox()
{
int msgboxID = MessageBox(
NULL, //I tried making this hWndApp as well, but no difference
(LPCWSTR)L"Cancel to exit or start the app and click Retry.",
(LPCWSTR)L"Application Not Found!",
MB_ICONSTOP | MB_RETRYCANCEL | MB_SYSTEMMODAL | MB_SETFOREGROUND
);
switch (msgboxID)
{
case IDCANCEL:
exit(EXIT_FAILURE);
case IDRETRY:
getProcessHandleAndPID();
break;
default:
//GetLastError();
exit(EXIT_FAILURE);
}
return msgboxID;
}
//------------------------------------------------
// Function to check if application is running /
//----------------------------------------------
void appCheck() {
if (!FindWindow(NULL, _T("NameOfApplication"))) {
getProcessHandleAndPID();
}
}
//--------------------------------------------------
// Function to get process handle and PID of app /
//------------------------------------------------
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (!hWndApp) {
appCheck();
}
switch (message)
{
case WM_PAINT:
//Code here
break;
case WM_CREATE:
//Code here
break;
case WM_COMMAND:
switch (HIWORD(wParam))
{
case BN_CLICKED:
if (LOWORD(wParam) == BTN_ENABLE) {
appCheck();
//Do stuff with button press
}
if (LOWORD(wParam) == BTN_DISABLE) {
appCheck();
//Do stuff with button press
}
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}

Not really an answer, but too long for comments:
This isn't your real code. Many things are missing, there are mismatched braces which would prevent compilation, etc. Always show your real code if you want help.
As David says, calling appCheck() every time you receive a message is the wrong approach. If you want to call it once after your window opens, do that before entering your message loop.
Your code is needlessly recursive (getProcessHandleAndPID() calls AppCheckMessageBox() which calls getProcessHandleAndPID() which calls...) and will potentially lead to a stack overflow.

Related

C++ Windows application menus stop responding

I'm an electrical engineer and am creating my first C++ Windows 10 application in Visual Studio.
When I start the app that I've created, and my application window starts with its menus, I can open a file and start processing that file. This processing takes several minutes and
can't be interrupted for too long (less than a millisecond - hopefully).
The problem I'm having is that when the file processing is underway my window's menus don't respond. This is tolerable when I'm running under the Visual Studio IDE, but when I run the standalone app's .exe file then the app's graphics soon stops rendering and Windows posts a "Not responding" error message.
Can someone please point me in the right direction to solve these related problems. There must be a simple way to temporarily give control back to WinMain or window_callback.
Here's a simplified structure of the code:
LRESULT CALLBACK window_callback(HWND hwnd, UINT uMsg, ...) {
switch (uMsg) {
case WM_CREATE:
AddMenus(hwnd);
break;
case MY_FILE_OPEN:
open_file(hwnd);
break;
...
}
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, ...) {
// Create Window Class
...
// Register Class
...
// Create Window
HWND window = CreateWindow(window_class.lpszClassName, L"My Window NAME", ...);
hdc = GetDC(window);
// My application's initialization code
...
while (running) {
MSG message;
while (PeekMessage(&message, window, ...) {
TranslateMessage(&message);
DispatchMessage(&message);
}
}
}
void open_file(HWND hwnd) {
here's where I call the file processing code (a several-minute loop);
}
If your application is not running the main message processing loop of PeekMessage, TranslateMessage, and DispatchMessage then it will become completely non-responsive as you have noticed. That's the nature of message-driven event loops such as used by Windows.
You either need to run open_file in a different thread, or segment it in some way that it can process a small piece at a time and return and get called again to process another piece.
E.g.
while (running) {
MSG message;
while (PeekMessage(&message, window, ...) {
TranslateMessage(&message);
DispatchMessage(&message);
}
open_file_piece();
}

Disable task switching keys with c++

I've done a lot of searching around with no real solution (to my own problem) so I thought I'd ask here.
I'm designing a kiosk-like program that prevents the user from using task keys (alt+tab, alt+esc, ctrl+esc, etc) while the program is running. Note I'm a novice programmer thus I'd want to stay away from separate dll handling if I can. Particularly, I have went to this site http://support.microsoft.com/kb/226359/en-us for the code. A simplified part of my code looks like this at the top:
HHOOK mule;
HHOOK g_hKeyboardHook;
BOOL g_bFullscreen;
LRESULT CALLBACK LowLevelKeyboardProc (INT nCode, WPARAM wParam, LPARAM lParam)
{
// By returning a non-zero value from the hook procedure, the
// message does not get passed to the target window
KBDLLHOOKSTRUCT *pkbhs = (KBDLLHOOKSTRUCT *) lParam;
BOOL bControlKeyDown = 0;
switch (nCode)
{
case HC_ACTION:
{
// Check to see if the CTRL key is pressed
bControlKeyDown = GetAsyncKeyState (VK_CONTROL) >> ((sizeof(SHORT) * 8) - 1);
// Disable CTRL+ESC
if (pkbhs->vkCode == VK_ESCAPE && bControlKeyDown)
return 1;
// Disable ALT+TAB
if (pkbhs->vkCode == VK_TAB && pkbhs->flags & LLKHF_ALTDOWN)
return 1;
// Disable ALT+ESC
if (pkbhs->vkCode == VK_ESCAPE && pkbhs->flags & LLKHF_ALTDOWN)
return 1;
break;
}
default:
break;
}
return CallNextHookEx (mule, nCode, wParam, lParam);
}
The my main is
int main(int argc, char **argv)
{
_getch();
g_hKeyboardHook = SetWindowsHookEx( WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), 0 );
cout << "Testing task keys disabling (alt tab, ctrl esc, alt esc) and taskbar..." << endl;
_getch();
UnhookWindowsHookEx( g_hKeyboardHook );
cout << "Re enabled" << endl;
_getch();
return 0;
}
I realize this code is for really old windows OS, but I've looked around and the other solutions resemble this code so I thought it should work.
But for some reason it doesn't seem to be working. Whenever my program gets to that line of code, the program stalls for like 5 seconds and continues to run, but the task keys are still working.
I've heard that I should be implementing that function as a dll instead of putting everything in one file, but I'm not sure if they're absolutely right (also I know nothing of dlls)
In addition, I've also tried code (to disable windows key) here: http://msdn.microsoft.com/en-us/library/windows/desktop/ee416808(v=vs.85).aspx and it does the same thing my own program (stalls and does nothing)
Can anyone spot where I did something wrong? I'm using VC++ 2010 on windows 7 64bit.
Your code is fine, hooks just doesn't work with console application because windows can't callback into a console application, it requires a message loop.
Read this answer by Hans Passant which applies here too.

Global keyboard hook with WH_KEYBOARD_LL and keybd_event (windows)

I am trying to write a simple global keyboard hook program to redirect some keys. For example, when the program is executed, I press 'a' on the keyboard, the program can disable it and simulate a 'b' click. I do not need a graphic ui, just a console is enough (keep it running)
My plan is to use global hook to catch the key input, and then use keybd_event to simulate the keyboard. But I have some problems.
The first problem is that the program can correctly block 'A' but if I hit 'A' on the keyboard once, the printf in the callback function is executed twice, as well as the keybd_event. So if i open a txt file, i click 'A' once, there are two 'B's input. why is that?
The second question is that why the hook using of WH_KEYBOARD_LL can work on other process without a dll? I thought that we had to use a dll to make a global hook until I wrote this example...
#include "stdafx.h"
#include <Windows.h>
#define _WIN32_WINNT 0x050
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
BOOL fEatKeystroke = FALSE;
if (nCode == HC_ACTION)
{
switch (wParam)
{
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
case WM_KEYUP:
case WM_SYSKEYUP:
PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)lParam;
if (fEatKeystroke = (p->vkCode == 0x41)) { //redirect a to b
printf("Hello a\n");
keybd_event('B', 0, 0, 0);
keybd_event('B', 0, KEYEVENTF_KEYUP, 0);
break;
}
break;
}
}
return(fEatKeystroke ? 1 : CallNextHookEx(NULL, nCode, wParam, lParam));
}
int main()
{
// Install the low-level keyboard & mouse hooks
HHOOK hhkLowLevelKybd = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, 0, 0);
// Keep this app running until we're told to stop
MSG msg;
while (!GetMessage(&msg, NULL, NULL, NULL)) { //this while loop keeps the hook
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UnhookWindowsHookEx(hhkLowLevelKybd);
return(0);
}
Many thanks!
Your callback function execute twice because of WM_KEYDOWN and WM_KEYUP.
When you down a key of your keyboard, windows calls the callback function with WM_KEYDOWN message and when you release the key, windows calls the callback function with WM_KEYUP message. That's why your callback function execute twice.
You should change your switch statement to this:
switch (wParam)
{
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
case WM_KEYUP:
case WM_SYSKEYUP:
PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)lParam;
if (fEatKeystroke = (p->vkCode == 0x41)) //redirect a to b
{
printf("Hello a\n");
if ( (wParam == WM_KEYDOWN) || (wParam == WM_SYSKEYDOWN) ) // Keydown
{
keybd_event('B', 0, 0, 0);
}
else if ( (wParam == WM_KEYUP) || (wParam == WM_SYSKEYUP) ) // Keyup
{
keybd_event('B', 0, KEYEVENTF_KEYUP, 0);
}
break;
}
break;
}
About your second question, I think you have already got from #Ivan Danilov answer.
First one is easy. You get one for key down and another for key up. :)
As for the why it can work without a DLL - that's because it is a global hook. Unlike thread-specific ones it is executed in your own process, not in the process where keyboard event happened. It is done via message sending to the thread which has installed the hook - that's precisely why you need message loop here. Without it your hook can't be ran as there would be no one to listen for incoming messages.
The DLL is required for thread-specific hooks because they're called in the context of another process. For this to work, your DLL should be injected into that process. It is just not the case here.
I have run your code but nothing happend? What wrong with me?
Base on msdn that WH_KEYBOARD_LL message is "Global only" It mean more than that.
The system calls this function .every time a new keyboard input event is about to be posted into a thread input queue.
This message is special case. You also need an DLL to make a real global hook for other message.

Handling Windows messages so that my application responds correctly

I had an old piece of code that I wrote about 15 years ago to do some file manipulation, which runs through a script to process 1/2 sourcefiles and output to 1/2 outputfiles and I've been trying to write it 'properly' so that it will run under Windows 7/8 as a scheduled task.
I've ported it to Visual Studio 2013 Express, and managed to get it to work (execute and generate the desired results) pretty quickly, processing my text input file, stripping rubbish out of it, and generating a formatted CSV file in about 38 seconds, however it Ghosts, and goes non-responsive until such time as the processing of the file completes, which is okish for user execution, but Windows 7 and 8 don't like running it as a scheduled task, and close it as soon as it ghosts.
I've tried re-writing the large chunk of processing code so that it returns to the main message handling loop after each line of script, and this functions, albeit about ten-twenty times slower (depending on whether I'm using GetMessage or PeekMessage, however I'm still struggling with the application ghosting, despite each line of script only taking a few milliseconds to run.
My Main Window code is currently;
while (msg.message != WM_QUIT)
{
while ((PeekMessage(&msg, NULL, 0, WM_COMMAND - 1, PM_REMOVE) > 0) ||
(PeekMessage(&msg, NULL, WM_COMMAND+1, 0xFFFF, PM_REMOVE) > 0))
// While there are any system messages with a value <> WM_COMMAND,
// Process these first
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) > 0)
// Process one WM_COMMAND message i.e. one of mine.
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
where my WndProc function has a giant case statement that processes all my posted messages to perform one sub-task of my file processing and all the windows system-type responses. I've cut out some of the 'doing stuff' commands, but you'll get the gist
it's a;
until we reach my iteration bit in the scriptfile;
process phase 1
until we finish processing the sourcefile or go round enough iterations;
process phase 2
until we reach the end of the sourcefile
process phase 3
end
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
//////////////////////////////
/* Start of my menu uptions */
//////////////////////////////
case MI_FILE_EXIT:
DestroyWindow(hWnd);
return(0);
case MI_RUN_EXECUTE:
// * Open Necessary Files * //
// * Start Processing ScriptFile * //
phase = 1;
command = 'A';
PostMessage(hWnd, WM_COMMAND, MI_PHASE_1, lParam);
return(0);
case MI_PHASE_1:
nextcommand = ProcessCommand(command);
if (ScriptFileComplete)
{
// We've reached the end of the script - stop processing
PostMessage(hWnd, WM_COMMAND, MI_SCRIPT_COMPLETE, lParam);
break;
}
else if (nextcommand = '<')
{
// prep for start of phase 2
phase = 2;
tiptr = tptr;
command = nextcommand;
PostMessage(hWnd, WM_COMMAND, MI_PHASE_2, lParam);
break;
}
else
{
// process the nextcommand
command = nextcommand;
PostMessage(hWnd, WM_COMMAND, MI_PHASE_1, lParam);
break;
}
return(0);
case MI_PHASE_2:
nextcommand = ProcessCommand(command);
redrawscreen(hWnd);
if (nextcommand == '>')
{
// we're at the end of the iteration
if (UseIterationCount)
{
IterationCount--;
if (IterationCount <= 0)
{
phase = 3;
command = nextcommand;
PostMessage(hWnd, WM_COMMAND, MI_PHASE_3, lParam);
break;
}
}
}
else if (ScriptFileComplete)
{
// We've reached the end of the script - stop processing
PostMessage(hWnd, WM_COMMAND, MI_SCRIPT_COMPLETE, lParam);
break;
}
else if (SourceFileAComplete)
// We've reached the end of the Source File - stop processing
{
PostMessage(hWnd, WM_COMMAND, MI_SCRIPT_COMPLETE, lParam);
break;
}
else // All's normal and we're just processing the next command
{
command = nextcommand;
PostMessage(hWnd, WM_COMMAND, MI_PHASE_2, lParam);
break;
}
return(0);
case MI_PHASE_3:
nextcommand = ProcessCommand(command);
command = nextcommand;
// test to see if we go round phase 3 loop again
if ((!ScriptFileComplete) && (!SourceFileAComplete))
{
PostMessage(hWnd, WM_COMMAND, MI_PHASE_3, lParam);
break;
}
else // we've cleared that and we're at scriptfile EOF
{
PostMessage(hWnd, WM_COMMAND, MI_SCRIPT_COMPLETE, lParam);
break;
}
return(0);
case MI_SCRIPT_COMPLETE:
// We're at the end of the script - close things down.
CloseFiles();
DrawMenuBar(hWnd);
if (AutoExit)
PostMessage(hWnd, WM_QUIT, wParam, lParam);
return(0);
case MI_DO_NOTHING: // blank code for initial entry to main message loop
return(0);
default: // somehow an invalid message was posted
log("invalid message was posted");
return(0);
}
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
redrawscreen(hWnd);
EndPaint(hWnd, &ps);
return(0);
case WM_DESTROY:
PostQuitMessage(0);
return(0);
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return(0);
}
So the idea is that after each call to processCommand (i.e. carry out one line of my script processing), return to the main message handle, respond to any events (like someone moving the window or clicking on the close button), and then process the next line of my script.
I'm clearly missing something (or lots of things) regarding which messages I should be checking and processing on a regular basis, so if anyone can offer suggestions/advice as to;
What messages should I be handling before all others?
How often should my application be checking for system messages?
Am I going about this completely wrong?
e.g. should I be threading the processing code? - the app shouldn't require any user interaction while it's running, but it would be good practise to allow a user to move/resize/quit it, which I was hoping to achieve through posting messages back to WM_COMMAND
Thank you very much for even reading this far. Any and all advice no matter how sharp (if it helps) appreciated.
Richard.
- UPDATE -
Thanks both for the pointers - it's clear that this does warrant threading my slow file access bits of code, so I've re-written to do this, but now I'm just a bit stuck as to where I should do fire off the thread / join afterwards - There's lots of examples where the thread is fired off in the main window and then joined straight afterwards e.g.;
void My_Slow_Task(){
; // Process lots of data
}
int main(){
std::thread t1(My_Slow_Task);
t1.join();
return 0;
}
but as pointed out below doing this in my message handling block just means it sits there like a lemon until the thread finishes, but I need a user to be able to make changes to the outputfiles etc. before they kick off the file manipulation process (it can be automated, but it needs to be able to not be as well), so at the moment, I'm after something like;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
// one of these messages is the menuitem for 'Run_my_big_chunk_of_processing' and sets 'ExecutingScript' to TRUE
// another will be to change the location of the output file or edit the script etc.
if (ExecutingScript == TRUE)
{
ExecutingScript = FALSE;
std::thread t1(Run_my_big_chunk_of_processing);
t1.join();
PostMessage(hWnd, WM_COMMAND, MI_RUN_COMPLETE, lParam);
// to do the close files, tidy up and feed back to the user.
}
}
If anyone's knows how I can handle the request from the user to start the slow process and fire it off, without the GUI having to wait for it to finish before handling other messages, then that'll be it sorted.
- SOLUTION? -
Use an outer control loop for user interaction while the thread isn't running, and an inner one for while it is;
_twinMain()
{
// Initialise Stuff
// Pre-exec message loop
// Outer messagehandling loop
while (!AllDone)
// we're !AllDone on entry, and AllDone when the app gets
// a WM_QUIT or other triggered abort e.g. script failure
{
// Pre/post-exec message loop
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (ExecutingScript)
// this will be set by auto-run in the ini file,
// or manually by a user clicking the menu option
{
std::thread t1(RunThread);
// Exec message loop
while (ExecutingScript)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) > 0)
// There may be no messages, as we could be in auto-run
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
t1.join();
PostMessage(hWnd, WM_COMMAND, MI_RUN_COMPLETE, lParam);
}
}
return (int) msg.wParam;
}
Thanks for all your help
VS2013 has the C++11 <thread> stuff, no need for non-standard libraries. std::aync(std::launch::async) will run a background task, std::future::wait_for allows you to check from the messsage loop whether the operation has finished. Of course, you can also use a old-style PostQuitMessage(WM_APP) from the processing thread. Either way, after the message loops exits, call .join() on the worked thread to clean it up, then exit the main thread.

How do I destroy a Window correctly?

I'm programming a little game, and I set the lpfnWndProc to DefWindowProc
and after that, I made a loop in that way:
MSG lastMessage;
while (true)
{
if (PeekMessage(
&lastMessage,
this->getWindow(),
0, 0,
PM_REMOVE))
{
TranslateMessage(&lastMessage);
DispatchMessage(&lastMessage);
}
}
So how do I handle the Close Window event in that case?
First of all, this is not how you write a message loop: it will take 100% CPU while waiting for messages, and won't remove messages for other windows from the queue. It will also never terminate. See here for an example of a message loop.
About closing windows: DefWindowProc will handle WM_CLOSE automatically and destroy your window. If you want your application to terminate when the window is closed, you need to handle WM_DESTROY and call PostQuitMessage(0) from it. This means you will need your own window procedure instead of DefWindowProc.
If you want WindowProc to be handled by a class, you do something like
class CWindow
{
static LRESULT WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
CWindow* self;
if(uMsg == WM_CREATE)
{
self = (CWindow*)((LPCREATESTRUCT)lParam)->lplpCreateParams;
}
else
self = GetWindowLong(hwnd,GWL_USERDATA);
if(self){
switch(uMsg){
case WM_CREATE:
return self->OnCreate(hwnd,(LPCREATESTRUCT)lParam);
case WM_CLOSE:
self->OnClose();
return 0;
// etc.
}
}
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
int OnCreate(HWND hwnd,LPCREATESTRUCT lpcs)
{
m_hwnd = hwnd;
SetWindowLong(m_hwnd,GWL_USERDATA,this);
return 0;
}
}
Making sure of course to pass 'this' as the last parameter to CreateWindow(Ex).
Next, In your message loop, you MUST check for WM_QUIT messages and use that as a cue to exit the loop. Also, NEVER do a filter on hwnd as that will prevent your application loop from dispatching messages for other windows on your thread. And many windows libraries create message windows on threads to facilitate inter process (and thread) comms. If you dont process all windows messages then (a) your game will eventually run out of memory, and (b) the entire system may start to act funny as your application will make IPC messages deadlock, or time out.
Also, WM_CLOSE is (usually) sent via SendMessage, not PostMessage. Sent messages are delivered straight to the window proc and can't be filtered in the app loop.