I have created a Window and a Thread in my Application. Now I want the thread to process some data and display it on the Main Window.
For this purpose, I have used PostMessage() funcion inside my thread.
i.e. A window is created, then a Thread is created. The thread applies some processing to data and Posts a Message to Main window that data should be displayed now.
But the problem is that for this purpose, I shall have to pass Window's Handle, While for this thread, Main Window Handle is an undeclared IDENTIFIER.
Is there any possible way in which I can pass the handle to Main Window to my thread so that using this Handle, the Thread is able to Post the Message.
Below is the code snippet for any help:
///Thread Function////
DWORD WINAPI threadFunction(LPVOID param)
{
//do something
PostMessage(hMainWin, WM_thread,0, 0);
return true;
}
////Main Function///
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{
const char AH_Glb_ClassName[] = "myWindClass";
WNDCLASSEX wc;
MSG Msg;
//Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = NULL;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = AH_Glb_ClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
HWND hMainWin; //Handle to Main WIndow
///Creating Main Window///
hMainWin = CreateWindowEx( WS_EX_CLIENTEDGE,
AH_Glb_ClassName,
"I am SERVER Window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
440,
120,
NULL, NULL, NULL, NULL);
if(hMainWin == NULL)
{
MessageBox(NULL,
"Window Creation Failed!",
"Error!",
MB_ICONEXCLAMATION |
MB_OK);
return 0;
}
ShowWindow(hMainWin,SW_MAXIMIZE);
UpdateWindow(hMainWin);
/////////////////THREAD////////////////
DWORD threadID = 0;
///Creating Thread///
HANDLE threadHandle = CreateThread(NULL,
0,
threadFunction,
0,
0,
&threadID);
return 0;
}
DWORD WINAPI threadFunction(LPVOID param)
{
HANDLE hwnd = (HANDLE)param;
}
...
HANDLE threadHandle = CreateThread(NULL,
0,
threadFunction,
(LPVOID)hMainWin,
0,
&threadID);
Thread function has LPVOID type, it matches the HANDLE type, both in Win32 and x64.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682453%28v=vs.85%29.aspx
BTW, you need to add message loop to WinMain.
Related
It's been years since I last worked with Windows API and I'm trying my hand at it again. I have a simple Window (with title "Test"). I put in the Window message handler under WM_CREATE, 2 CreateWindow calls to create a static and an edit control. I'm pretty sure the coordinates are decent (not overlapping or off the window rectangle). Am I putting the calls under the wrong event? It's just a simple window - not MDI or SDI or anything like that. Here is my code for the entire program. I hope it's sufficient to figure out what I'm doing wrong. I'm using Eclipse CDT with Cygwin's G++ compiler to build it....:
#include <windows.h>
BOOL InitApplication(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE hinstance, int nCmdShow);
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
BOOL InitApplication(HINSTANCE hInstance)
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = "";
wc.lpszClassName = "MainWindow";
return(RegisterClass(&wc));
}
BOOL InitInstance(HINSTANCE hinstance, int nCmdShow)
{
HINSTANCE hCurInstance = hinstance;
HWND hWnd = CreateWindow("MainWindow", "Test", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, (HWND)(NULL), (HMENU)(NULL), hCurInstance, (LPVOID)(NULL));
if(!hWnd)
return(FALSE);
// Show the window and send a WM_PAINT message to the window
// procedure.
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return(TRUE);
}
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CREATE:
CreateWindow("WC_STATIC", "&Test: ", SS_LEFT | WS_VISIBLE | WS_CHILD, 10, 10, 50, 20, hWnd, NULL, (HINSTANCE)(GetWindowLongPtr(hWnd, GWLP_HINSTANCE)), (LPVOID)(NULL));
CreateWindow("WC_EDIT", "", WS_BORDER | WS_TABSTOP | WS_VISIBLE | WS_CHILD | ES_LEFT, 60, 10, 50, 20, hWnd, NULL, (HINSTANCE)(GetWindowLongPtr(hWnd, GWLP_HINSTANCE)), (LPVOID)(NULL));
return(0);
default:
return(DefWindowProcA(hWnd, uMsg, wParam, lParam));
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmd, int nCmdShow)
{
BOOL fGotMessage;
MSG msg;
if(!InitApplication(hInstance))
return(FALSE);
if(!InitInstance(hInstance, nCmdShow))
return(FALSE);
while(((fGotMessage = GetMessage(&msg, (HWND) NULL, 0, 0)) != 0) && (fGotMessage != -1))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return(msg.wParam);
}
WM_CREATE is the correct "event" message to create the child controls in.
You are simply using the wrong class names for the child controls. That is why you are not seeing them. Had you checked the result of those CreateWindow() calls for failures, you would have noticed that CreateWindow() was returning NULL, and GetLastError() was reporting ERROR_CANNOT_FIND_WND_CLASS (1407).
You need to replace "WC_STATIC" with "Static", and replace "WC_EDIT" with "Edit". Or, you can use the pre-defined WC_STATIC and WC_EDIT constants that are defined in <commctrl.h>.
You can also replace GetWindowLongPtr(hWnd, GWLP_HINSTANCE) with NULL when creating system-defined classes, as they are registered globally, not per-module. The HINSTANCE parameter of CreateWindow/Ex() is ignored for them.
On a side note: your GetMessage() loop can be simplified to just:
while (GetMessage(&msg, (HWND) NULL, 0, 0))
See: When will GetMessage return -1?
I am trying to display a combobox window as you can see I set hWndComboBox as my second window and I am using ShowWindow() function and it does not really show anything when I compile and run the code? What should I add more?
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstace, LPSTR lpCommand, int nCmdLine)
{
HWND window;
int xpos = 100; // Horizontal position of the window.
int ypos = 100; // Vertical position of the window.
int nwidth = 200; // Width of the window
int nheight = 200; // Height of the window
HWND hwndParent = window; // Handle to the parent window
MSG message;
WNDCLASSEX wndClass;
wndClass.cbSize = sizeof(WNDCLASSEX);
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.style = 0;
wndClass.hInstance = hInstance;
wndClass.lpfnWndProc = wndCll;
wndClass.lpszClassName = classNoOne;
wndClass.lpszMenuName = MAKEINTRESOURCE(IDR_MYMENU);
wndClass.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_PENGUIN_ICON));
wndClass.hIconSm = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_PENGUIN_ICON), IMAGE_ICON, LR_DEFAULTSIZE, LR_DEFAULTSIZE, 0);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW-1);
if(!RegisterClassEx(&wndClass)){
printf("No wndclass");
}
window = CreateWindowEx(WS_EX_CLIENTEDGE, classNoOne, "Start Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 1000, 500, NULL, NULL, hInstance, NULL);
//create the window
HWND hWndComboBox = CreateWindow(WC_COMBOBOX, "name of the combobox", CBS_DROPDOWN | CBS_HASSTRINGS | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE , xpos, ypos, nwidth, nheight, hwndParent, NULL, hInstance, NULL);
TCHAR Planets[9][10] = {
TEXT("MERCURY"), TEXT("VENUS"), TEXT("Terra"), TEXT("MARS"), TEXT("JUPITER"), TEXT("SATURN"), TEXT("URANUS"), TEXT("NEPTUNE"), TEXT("PLUTO")
};
//these are the list elements
TCHAR A[16];
int k = 0;
memset(&A, 0, sizeof(A));
//allocate memory
for(k = 0; k<=8; k+=1){
strcpy(A, (TCHAR *)Planets[k]);
SendMessage(hWndComboBox,(UINT) CB_ADDSTRING,(WPARAM) 0,(LPARAM) A);
}
SendMessage(hWndComboBox, CB_SETCURSEL, (WPARAM)2, (LPARAM)0);
ShowWindow(hWndComboBox, nCmdLine);
//ShowWindow(window, nCmdLine);
if(window == NULL){
printf("window is NULL");
}
while(GetMessage(&message, NULL, 0, 0) > 0){
if(!IsDialogMessage(dialogSmall, &message)){
TranslateMessage(&message);
DispatchMessage(&message);
}
}
return message.wParam;
}
Programming languages do not work like mathematics. In mathematics you can say x = y; and then say y = 5; and then you can infer that x must be 5.
In programming languages however, when you say HWND hwndParent = window; then hwndParent takes the value that window had at the moment of the assignment, so if you later actually initialize window with window = ... you cannot expect the value of hwndParent to suddenly become meaningful. It will stay uninitialized, since window was uninitialized at the time of the assignment.
Hint: if you have been able to do HWND hwndParent = window; when window was uninitialized, this means that you received no warning about it. Which in turn means that you have not configured your compiler to issue warnings when you do things like that. Do not try to program without warnings. You will never accomplish much this way.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have been using the below code to make a simple window within C. When Compiling a get the error C4133, ive brought up the error in visual online but unable to resolve. (Apologies this is badly written)
#include <windows.h>
const char g_szClassName[] = "myWindowClass";
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
//Step 1: Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
// Step 2: Creating the Window
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"The title of my window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
NULL, NULL, hInstance, NULL);
if (hwnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// Step 3: The Message Loop
while (GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
I tried your code in Visual Studio 2015, in case the character set is "not set" or "multi byte" everything compiles without any errors or warnings.
Also the window is shown if I execute the exe.
"Unicode fails" because ansi strings are used.
So I suppose you need to change to ansi "not set" for the used character set.
Otherwise additional information for the error are necessary (line etc) compiler settings VStudio version?
Your problem has been explained in the answer from Bjoern. Actually the usage of the old ascii version of winapi is becoming rare, the preference is for unicode (widechar) version code.
Anyway there is a way to write code independent from the ansi/widechar version using the _T() macro and the generic tchar macros.
Try you emended code with ascii and unicode compilations:
#include <windows.h>
#include <tchar.h>
TCHAR g_szClassName[] = _T("myWindowClass");
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
//Step 1: Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, _T("Window Registration Failed!"), _T("Error!"), MB_ICONEXCLAMATION | MB_OK);
return 0;
}
// Step 2: Creating the Window
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, g_szClassName, _T("The title of my window"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 240, 120, NULL, NULL, hInstance, NULL);
if (hwnd == NULL)
{
MessageBox(NULL, _T("Window Creation Failed!"), _T("Error!"), MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// Step 3: The Message Loop
while (GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
I am creating a window with the following code
int WINAPI WinMain(HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow){
MSG messages;
WNDCLASSEX wc;
DWORD dwrd;
InitCommonControls();
//The Window structure
wc.hInstance = hThisInstance;
wc.lpszClassName = szClassName;
wc.lpfnWndProc = WindowProcedure;
wc.style = CS_DBLCLKS;
wc.cbSize = sizeof(WNDCLASSEX);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); //if I comment it RegisterClassEx(&wc) fails with error: ERROR_INVALID_PARAMETER
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszMenuName = 0;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = CreateSolidBrush(RGB(230, 225, 208)); //(HBRUSH)(COLOR_3DFACE + 1);
//Register the window class, and if it fails quit the program
if(!RegisterClassEx(&wc)){
dwrd = GetLastError();
printf("Error in Function = WinMain() at line = %d, with error code = %X \n", __LINE__ - 3, (unsigned int)dwrd);
exit(EXIT_FAILURE);
}
//more code
}
When I comment out the line
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&wc) fails with error: ERROR_INVALID_PARAMETER
Thank you
When you comment out that line, the wc.hIconSm field does not get initialized and likely contains garbage values. RegisterClassEx() happens to notice this and complains.
RegisterClassEx(&wc) will not work as you did not use WNDCLASSEX. Either use WNDCLASS and RegisterClass or WNDCLASSEX and RegisterClassEx.
I am trying to create a very basic window using the Win32 API and it's been a long time since I've done this.
I think my message loop is okay, but when I close the opened window, the application is still running. It looks like the message loop never gets a WM_QUIT message. However, I am calling PostQuitMessage and a message box confirms I called it.
What is wrong with this minimalist code?
#include <Windows.h>
LRESULT CALLBACK window_proc(HWND hwnd, UINT msg,
WPARAM w_param, LPARAM l_param) {
switch (msg) {
case WM_DESTROY:
MessageBox(NULL, L"destroy", L"info", MB_OK);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, w_param, l_param);
}
return 0;
}
int CALLBACK WinMain(HINSTANCE h_instance, HINSTANCE h_prev_instance,
LPSTR cmd_line, int n_cmd_show) {
WNDCLASS wnd_class;
HWND hwnd;
MSG msg;
BOOL ret;
wnd_class.cbClsExtra = 0;
wnd_class.cbWndExtra = 0;
wnd_class.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
wnd_class.hCursor = LoadCursor(NULL, IDC_ARROW);
wnd_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wnd_class.hInstance = h_instance;
wnd_class.lpfnWndProc = window_proc;
wnd_class.lpszClassName = L"MyWindowClass";
wnd_class.lpszMenuName = NULL;
wnd_class.style = 0;
if (!RegisterClass(&wnd_class)) {
MessageBox(NULL, L"cannot register window class",
L"error", MB_OK | MB_ICONERROR);
}
hwnd = CreateWindow(
L"MyWindowClass",
L"",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
h_instance,
NULL
);
while ((ret = GetMessage(&msg, hwnd, 0, 0)) != 0) {
if (ret == -1) {
MessageBox(NULL, L"error", L"", MB_OK);
} else {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
MessageBox(NULL, L"quitting now", L"info", MB_OK);
return msg.wParam;
}
The GetMessage doc says the function returns 0 when it reads a WM_QUIT message. Howcome PostQuitMessage is called and GetMessage never returns 0?
Thank you, Win32 gurus.
Its your GetMessage() loop.
You're passing your window handle to that loop, thereby filtering out all application-thread messages and only receiving messages to that window. .
Change this:
while ((ret = GetMessage(&msg, hwnd, 0, 0)) != 0)
// Note window handle =========^
To this:
while ((ret = GetMessage(&msg, NULL, 0, 0)) != 0)
// Note no handle =============^
And your application thread queue should now be monitored by your GetMessage() loop.
Why: GetMessage() invokes can be tailored to monitor a specific window handle's message queue. The application WM_QUIT is not posted to a window handle queue; it is posted to the thread-message queue, which can only pull messages off the queue by using GetMessage() (perhaps PeekMessage() as well, but its been too long for me to remember) with no target window handle to specifically monitor.