When I create a window in C using the CreateWindow() function, it works fine it just disappears instantly, so I used the getch() function to try to resolve the issue but it does not work. The window does not display the button, and crashes.
But when I used MessageBox() instead of getch(), it stays and functions normally. I am trying to figure out why this happens.
I tried many things, like using MessageBox() and getch() together, using getch() before and after ShowWindow(), but every time it gives me some interesting result but not the normal functionality of the window.
Code that works:
#include <windows.h>
int _stdcall WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
{
HWND h;
HINSTANCE i;
h = CreateWindow("Button", "XYZ", WS_OVERLAPPEDWINDOW, 15, 20, 250, 200, 0, 0, i, 0);
ShowWindow(h, nCmdShow);
MessageBox(0, "Stop", "Wait", MB_OK);
return 0;
}
Code that does not work:
#include <windows.h>
int _stdcall WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
{
HWND h;
HINSTANCE i;
h = CreateWindow("Button", "XYZ", WS_OVERLAPPEDWINDOW, 15, 20, 250, 200, 0, 0, i, 0);
ShowWindow(h, nCmdShow);
getch();
return 0;
}
I want to know the reason for this error. I think it is because getch() is a DOS function, but still the compiler should at least show a warning.
There is no crash in this code.
Your getch() example simply lacks a message loop needed to service the window, and also getch() is meaningless in a non-console app. So your WinMain() exits immediately after showing the button window.
Whereas your MessageBox() example has a message loop (inside of MessageBox() itself) which keeps WinMain() running, and the button window processong UI messages, until the MessageBox dialog is closed.
Also, it doesn't make sense to try to display a button as its own overlapped window. You should be registering and creating a separate overlapped window that then creates the button as a child. User actions on the button are sent to the button's parent window, so you need to create a parent window for it.
Related
Using the Win32 APIs, is it possible to create a Window or Dialog in one thread then collect events for it from another thread?
Are HWNDs tied to threads?
Trying the contrived example below I never see GetMessage() fire.
HWND g_hWnd;
DWORD WINAPI myThreadProc(LPVOID lpParam)
{
while(GetMessage(&msg, hWnd, 0, 0) > 0)
{
...
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
hWnd = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_MYDIALOG), 0, myDlgProc);
CreateThread(NULL, 0 myThreadProc, NULL, 0, NULL);
...
}
But here, I do.
HWND g_hWnd;
HINSTANCE g_hInstance;
DWORD WINAPI myThreadProc(LPVOID lpParam)
{
hWnd = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_MYDIALOG), 0, myDlgProc);
while(GetMessage(&msg, hWnd, 0, 0) > 0)
{
...
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
g_hInstance = hInstance;
CreateThread(NULL, 0 myThreadProc, NULL, 0, NULL);
...
}
Can somebody explain what I'm seeing?
No.
GetMessage returns messages on the current thread's input queue. The HWND parameter is a filter, so that GetMessage only returns messages in the current thread's input queue intended for that window.
Windows have thread affinity - messages intended for a window get handled on the thread that created and therefore owns the window.
From the MSDN:
The GetMessage function retrieves a
message from the calling thread's
message queue
So no, what you describe is not directly possible.
In your first example the Dialog and GetMessage are in separate threads. And the documentation says:
The GetMessage function retrieves a message from the calling thread's message queue.
The second example works since the calling thread (for GetMessage) also owns the Dialog.
Use AttachThreadInput.
In your example programm finish after create window.
But anyway in win32 all threads have own message queue.
And all message queues get messages for windows created in this thread.
see:
http://msdn.microsoft.com/en-us/library/ms644928(VS.85).aspx (Using Messages and Message Queues)
http://msdn.microsoft.com/en-us/library/ms644936(VS.85).aspx (GetMessage Function)
You can of course change the window procedure that handles messages for any window. Check the SetWindowLong function - http://msdn.microsoft.com/en-us/library/ms633591(VS.85).aspx - there are some rules as to what address space the new proc is. I suggest using a dll. Another way is to sub class the window message queue.
Of course you can !
Just use remote code injection ! (very classic !)
I want to detect when the mouse is pressed on my wallpaper.
So I got the wallpaper handle and now I'm trying to add a message loop to it, but its not working for some reason.
Here's my code so far:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow)
{
HWND hWallPaper = getWallPaperHWND();
if (hWallPaper != NULL)
{
MSG msg;
while (GetMessage(&msg, hWallPaper, 0, 0))
{
MessageBox(NULL, "msg", "got message", MB_OK);
}
}
else
MessageBox(NULL,"Window wasn't found","window not found",MB_OK);
return 0;
}
Why isn't it showing a message box when I fire an even on the wallpaper, like when I click on it or even just move the mouse?
I want to add a statusbar to my Win32 application. I found out that I can use CreateStatusWindow function. I works fine until I re-size my window. See a part of my block of code:
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
CreateStatusWindow(WS_CHILD | WS_VISIBLE, _T("Welcome to SpyWindows"), hWnd, 9000);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
Here are two printscreens of my application main window:
What can I do to have a good status bar? (I also want to divide it in more areas)
The documentation mentions that the status bar will recompute its appropriate position and size when it receives a WM_SIZE message:
The window procedure automatically adjusts the size of the status bar
whenever it receives a WM_SIZE message. Typically, when the size of
the parent window changes, the parent sends a WM_SIZE message to the
status bar.
So, the simplest way to achieve this is to relay to the status bar the WM_SIZE messages received by the parent (with SendMessage(), from its window procedure). The message parameters do not matter, as the status bar does not use them in its computations.
Hello Everyone,
I want to know if there is an image control in VC++ like there is one in VB. Actually using the picture box i face the problem of not being able to re size the image at design time for my dialog. But in image control this is possible. I there is no image control is there a way to check the height and width of a dialog from the dialog editor at design time ???
If you're writing an unmanaged C or C++ project it's a little bit more difficult than using the PictureBox control that would be available when designing managed Windows Forms application, but still doable.
If you are using a DialogBox resource for the window (note: I wrote this part using Visual Studio 2015 as a reference, not 2008, but the general process should be the same):
Insert the image as a resource in your project. Let's say we named the resource for the bitmap IDB_BITMAP1 for simplicity.
Create a new Static child window in the dialog box.
Right click on the new Static window and select Properties.
Under the Misc subheading in Properties, change Type to Bitmap.
Under the Misc subheading in Properties, change Image to IDB_BITMAP1.
If you are hand-coding the window (i.e. manually writing calls to CreateWindow and CreateWindowEx to create the window):
Insert the image as a resource in your project. Make sure to add the line #include "resource.h" to your code.
Get a handle to the bitmap using the LoadBitmap function.
Create the static window as a child window of the main window, and specify the SS_BITMAP window style.
Send the STM_SETIMAGE message to the window using the previously identified handle to the bitmap resource.
Example code, assuming your image is IDB_BITMAP1:
#include <Windows.h>
#include <tchar.h>
#include "resource.h"
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd)
{
HWND hWnd, hStcImage;
MSG Msg;
HBITMAP hBitmap = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP1));
// ... register the window class etc
hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, _T("ExampleClassName"), _T("Simple Window"), WS_VISIBLE | WS_SYSMENU, 100, 100, 350, 370, NULL, NULL, hInstance, NULL);
hStcImage = CreateWindow(_T("Static"), NULL, WS_VISIBLE | WS_CHILD | SS_BITMAP, 10, 10, 0, 0, hWnd, NULL, hInstance, NULL);
SendMessage(hStcImage, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hBitmap);
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
while (GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
Using the Win32 APIs, is it possible to create a Window or Dialog in one thread then collect events for it from another thread?
Are HWNDs tied to threads?
Trying the contrived example below I never see GetMessage() fire.
HWND g_hWnd;
DWORD WINAPI myThreadProc(LPVOID lpParam)
{
while(GetMessage(&msg, hWnd, 0, 0) > 0)
{
...
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
hWnd = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_MYDIALOG), 0, myDlgProc);
CreateThread(NULL, 0 myThreadProc, NULL, 0, NULL);
...
}
But here, I do.
HWND g_hWnd;
HINSTANCE g_hInstance;
DWORD WINAPI myThreadProc(LPVOID lpParam)
{
hWnd = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_MYDIALOG), 0, myDlgProc);
while(GetMessage(&msg, hWnd, 0, 0) > 0)
{
...
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
g_hInstance = hInstance;
CreateThread(NULL, 0 myThreadProc, NULL, 0, NULL);
...
}
Can somebody explain what I'm seeing?
No.
GetMessage returns messages on the current thread's input queue. The HWND parameter is a filter, so that GetMessage only returns messages in the current thread's input queue intended for that window.
Windows have thread affinity - messages intended for a window get handled on the thread that created and therefore owns the window.
From the MSDN:
The GetMessage function retrieves a
message from the calling thread's
message queue
So no, what you describe is not directly possible.
In your first example the Dialog and GetMessage are in separate threads. And the documentation says:
The GetMessage function retrieves a message from the calling thread's message queue.
The second example works since the calling thread (for GetMessage) also owns the Dialog.
Use AttachThreadInput.
In your example programm finish after create window.
But anyway in win32 all threads have own message queue.
And all message queues get messages for windows created in this thread.
see:
http://msdn.microsoft.com/en-us/library/ms644928(VS.85).aspx (Using Messages and Message Queues)
http://msdn.microsoft.com/en-us/library/ms644936(VS.85).aspx (GetMessage Function)
You can of course change the window procedure that handles messages for any window. Check the SetWindowLong function - http://msdn.microsoft.com/en-us/library/ms633591(VS.85).aspx - there are some rules as to what address space the new proc is. I suggest using a dll. Another way is to sub class the window message queue.
Of course you can !
Just use remote code injection ! (very classic !)