I'm just trying to learn a little bit of C++ and wrote a few lines that do nothing but open a window.
I've added a Message Handler too and by clicking the [X] on my window it closes as its supposed to.
As the next step I wanted the Program to terminate when the [X] is clicked but it does'nt do that.
Here's my code:
#include <Windows.h>
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
switch (msg){
case WM_CLOSE:
PostQuitMessage(88);
break;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE pPrevInstance, LPSTR lpCmdLine, int cCmdShow) {
const auto pClassName = "M3D";
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof(wc);
wc.style = CS_OWNDC;
wc.lpfnWndProc = DefWindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = nullptr;
wc.hCursor = nullptr;
wc.hIcon = nullptr;
wc.hCursor = nullptr;
wc.hbrBackground = nullptr;
wc.lpszMenuName = nullptr;
wc.lpszClassName = pClassName;
RegisterClassEx(&wc);
HWND hWnd = CreateWindowEx(0, pClassName, "Fenster M3D", WS_CAPTION | WS_MAXIMIZEBOX | WS_SYSMENU, 200, 200, 640, 480, nullptr, nullptr, hInstance, nullptr);
//Fenster aufrufen
ShowWindow(hWnd, SW_SHOW);
//
//message Pumpe
MSG msg;
while (GetMessage(&msg,nullptr,0,0) > 0){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
Can anyone tell my whats wrong and why my PostQuitMessage() wont do its job?
The other threads I've found werent really helping
The problem is on this assignment:
wc.lpfnWndProc = DefWindowProc;
You are telling the message loop to dispatch messages directly to DefWindowProc(), so your custom WndProc() is never used, so PostQuitMessage() is never called. DefWindowProc() does not call PostQuitMessage() for any message that it processes.
Change that assignment to this instead:
wc.lpfnWndProc = WndProc;
Also, per the Closing the Window documentation on MSDN, DefWindowProc() calls DestroyWindow() when processing WM_CLOSE, so you should call PostQuitMessage() in reply to WM_DESTROY instead:
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
switch (msg){
case WM_DESTROY:
PostQuitMessage(88);
break;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
Related
I'm trying to make a window for DirectX, but for some reason, when the window is created, it can't be closed after pressing X and it becomes a zombie process. I found that the GetMessage loop did not call WndProc at all after pressing X. I tried to find a solution, but unsuccessfully, so I want to ask the community. Please advise me.
#include <Windows.h>
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int
nCmdShow)
{
//register windows class
const wchar_t* pClassName = L"Senko Interaction";
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof(wc);
wc.style = CS_OWNDC;
wc.lpfnWndProc = DefWindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = nullptr;
wc.hCursor = nullptr;
wc.hbrBackground = nullptr;
wc.lpszMenuName = nullptr;
wc.lpszClassName = pClassName;
wc.hIconSm = nullptr;
RegisterClassEx(&wc);
//create window instance
HWND hWnd = CreateWindowEx(
0,
pClassName,
L"Senko Interaction",
WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU,
0, 0, 1280, 720,
nullptr, nullptr, hInstance, nullptr
);
ShowWindow(hWnd, SW_SHOW);
//create message loop
MSG msg;
BOOL gResult;
while ((gResult = GetMessage(&msg, nullptr, 0, 0)) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (gResult == -1)
{
return -1; //return -1
}
else
{
return msg.wParam; //return 0
}
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CLOSE:
PostQuitMessage(1);
break;
}
return DefWindowProc(hWnd, message, wParam, lParam); //return 1
}
You set your window class to use DefWindowProc() instead of WndProc() for the lpfnWndProc, so it makes sense why WndProc() is never called:
wc.lpfnWndProc = DefWindowProc; // WRONG
That should be:
wc.lpfnWndProc = WndProc; // CORRECT
Im trying to create a windows application with winapi. So i want to have one parent window and one child window in it. Here is my code:
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK ChildProc(HWND, UINT, WPARAM, LPARAM);
const char szChildName[] = "Child window title";
const UINT PM_COLORCHANGED = WM_APP + 1;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
MSG msg;
HWND hWnd;
WNDCLASS wc;
char szAppName[] = "title";
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = (LPCWSTR)szAppName;
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);
wc.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
wc.hIcon = NULL;
wc.lpfnWndProc = ChildProc;
wc.lpszClassName = (LPCWSTR)szChildName;
RegisterClass(&wc);
hWnd = CreateWindow((LPCWSTR)szAppName,
(LPCWSTR)szAppName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hWnd, iCmdShow);
UpdateWindow(hWnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND hChild;
static RECT rect;
switch (message)
{
case WM_CREATE:
{
GetClientRect(hWnd, &rect);
hChild = CreateWindow((LPCWSTR)szChildName,
NULL,
WS_CHILD | WS_VISIBLE | WS_DLGFRAME,
5,
rect.bottom - 35,
rect.right - 10,
30,
hWnd,
NULL,
((LPCREATESTRUCT)lParam)->hInstance,
NULL);
return 0;
}
case WM_SIZE:
{
return 0;
}
case PM_COLORCHANGED:
{
return 0;
}
case WM_PAINT:
{
return 0;
}
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
LRESULT CALLBACK ChildProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_SIZE:
{
return 0;
}
case WM_LBUTTONDOWN:
{
return 0;
}
case WM_PAINT:
{
return 0;
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
This works perfect, so i see the child window at the bottom of the application.
But, instead of WNDCLASS I want to use WNDCLASSEX, which forces me to use RegisterClassEx() to register the windows. Also I want to use CreateWindowEx, my code looks like that:
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK ChildProc(HWND, UINT, WPARAM, LPARAM);
const char szChildName[] = "Child name";
const UINT PM_COLORCHANGED = WM_APP + 1;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
MSG msg;
HWND hWnd;
WNDCLASSEX wc;
char szAppName[] = "The Child Window";
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbClsExtra = 0;
wc.cbSize = sizeof(WNDCLASSEX);
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = NULL;
wc.hIconSm = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.lpszClassName = (LPCWSTR)szAppName;
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wc);
wc.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
wc.hIcon = NULL;
wc.lpfnWndProc = (WNDPROC)ChildProc;
wc.lpszClassName = (LPCWSTR)szChildName;
RegisterClassEx(&wc);
hWnd = CreateWindowEx(NULL,
wc.lpszClassName,
L"parent window",
(WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU),
200,
150,
1000,
1000,
NULL,
NULL,
hInstance,
NULL
);
ShowWindow(hWnd, iCmdShow);
UpdateWindow(hWnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND hChild;
static RECT rect;
switch (message)
{
case WM_CREATE:
{
GetClientRect(hWnd, &rect);
hChild = CreateWindowEx(NULL,
(LPCWSTR)szChildName,
L"child window",
(WS_CHILD | WS_VISIBLE | WS_DLGFRAME),
200,
150,
200,
200,
hWnd,
NULL,
((LPCREATESTRUCT)lParam)->hInstance,
NULL
);
return 0;
}
case WM_SIZE:
{
return 0;
}
case PM_COLORCHANGED:
{
return 0;
}
case WM_PAINT:
{
return 0;
}
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
LRESULT CALLBACK ChildProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_SIZE:
{
return 0;
}
case WM_LBUTTONDOWN:
{
return 0;
}
case WM_PAINT:
{
return 0;
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
The problem: Now i only see the color of the child window, so the whole application has this background color of the child window, so somehow the pc repainted everything in the color of the child window. (no child window is even visible, everything i see is only this LTGRAY_Brush of the child window.
Weird is: If i delete the line where the child window is created, so this line:
hChild = CreateWindowEx(NULL,
(LPCWSTR)szChildName,
L"child window",
(WS_CHILD | WS_VISIBLE | WS_DLGFRAME),
200,
150,
200,
200,
hWnd,
NULL,
((LPCREATESTRUCT)lParam)->hInstance,
NULL
then even now, the background color gets the same as the one that i registered the child class with. Altough the child class hasn't been created. Thanks for your help.
My requirement is that:
I want to detect left mouse click event and take some action. Mouse click should get detected only on the given application if mouse click is on other application then it should not take action.
Currently I am using :
mousehook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProc, NULL, 0);
LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
PKBDLLHOOKSTRUCT k = (PKBDLLHOOKSTRUCT)(lParam);
POINT p;
if (wParam == WM_LBUTTONDOWN)
{
// MB1 click
}
return CallNextHookEx(0, nCode, wParam, lParam);
}
but it is working for mouse click anywhere on the desktop screen. I want to detect it for current application only.
If you have Win32 application. Probably you can handle mouse events in your Window proc itself.
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_LBUTTONDOWN:
// your code
return 0;
case WM_LBUTTONUP:
// your code
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
Window creation:
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("Connect");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
if (!RegisterClass(&wndclass)) {
MessageBox(NULL, TEXT("Program requires Windows NT!"), szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, TEXT("Connect−the−Points Mouse Demo"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
In WINAPI, I have seen a virus which displays an icon on the x-y of the mouse whenever a mouse click event occurs (the red one which has a white X inside). How do I show an icon like that whenever I click the mouse? I know how to hook mouse clicks with setwindowshookex. Is there a function like iconshow as I have shown below.
HHOOK msHOOK;
//getting the icon let's say from a rc file
HICON redIcon;
msHOOK = SetWindowsHookEx(WH_MOUSE_LL, mouseProc, NULL, 0);
LRESULT CALLBACK mouseProc(int nCode, WPARAM wPar, LPARAM lPar){
IconShow(NULL, redIcon, xofMouse, yofMouse, 0);
MessageBox(NULL, "Icon showed", "Cap", 0);
return CallNextHookEx(NULL, nCode, wPar, lPar);
}
while(GetMessage(&msg, NULL, 0, 0) > 0){
TranslateMessage(&msg);
}
Thanks
UPDATE
#include <windows.h>
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdParam, int iCmdShow){
HWND wnd;
MSG msg;
WNDCLASSEX wc;
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);
wc.lpszMenuName = NULL;
wc.lpszClassName = "ClassName";
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wnd = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_LAYERED, "ClassName", "ss", NULL, CW_USEDEFAULT, CW_USEDEFAULT, 100, 100, NULL, NULL, NULL, NULL);
SetLayeredWindowAttributes(wnd, RGB(255, 255, 0), 20, LWA_COLORKEY);
ShowWindow(wnd, SW_SHOW);
while (GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
}
return 0;
}
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;
case WM_PAINT:
//stuff here
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
You would have to create your own always-on-top window to display the cursor.
It probably needs to be a layered window so you can use UpdateLayeredWindow() and a 32-bit RGBA bitmap to get every cursor looking correct.
If you are only using a specific cursor you control, and it does not have an alpha channel, you can save yourself some work by painting the image as-is onto your window in a WM_ERASEBKGND or WM_PAINT message handler, and then use SetLayeredWindowAttributes(..., LWA_COLORKEY, ...) to set the window's transparency color.
I tried to build my Win32 API project for x64 with Visual Studio 2013. But the routed WindowProc Callback isn't working properly. I'm using SetWindowLongPtr/GetWindowLongPtr together with GWLP_USERDATA to store an this pointer of my window. In the past I used SetWindowLong/GetWindowLong and GWL_USERDATA for this purpose - but these are gone on x64. However on x86 everything still works fine (even with SetWindowLongPtr/GetWindowLongPtr and GWLP_USERDATA), but on x64 there's an access violation as soon as I try to access any method/member inside my member function WindowProc.
#include <windows.h>
#include <stdio.h>
#include "main.h"
class Window{
public:
Window(const char* title, const float width, const float height){
char windowClass[255];
sprintf_s(windowClass, "WindowClass%s", title);
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = WindowProcRouter;
wc.hInstance = nullptr;
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = windowClass;
RegisterClassEx(&wc);
DWORD dwStyle = WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU;
RECT WindowRect;
WindowRect.left = (long)0;
WindowRect.right = (long)width;
WindowRect.top = (long)0;
WindowRect.bottom = (long)height;
AdjustWindowRect(&WindowRect, dwStyle, FALSE);
hWnd = CreateWindowEx(0,
windowClass,
title,
dwStyle,
0, 0,
WindowRect.right - WindowRect.left,
WindowRect.bottom - WindowRect.top,
nullptr,
nullptr,
wc.hInstance,
(LPVOID) this);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
ShowWindow(hWnd, SW_SHOW);
SetFocus(hWnd);
closed = false;
}
static LRESULT CALLBACK Window::WindowProcRouter(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
LRESULT returnValue = 0;
Window* pWnd = nullptr;
if (uMsg == WM_NCCREATE){
SetWindowLongPtr(hWnd, GWLP_USERDATA,
(long)((LPCREATESTRUCT(lParam))->lpCreateParams));
}
pWnd = (Window*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
if (pWnd){
returnValue = pWnd->WindowProc(hWnd, uMsg, wParam, lParam);
}
else{
returnValue = DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return returnValue;
}
LRESULT CALLBACK Window::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
switch (uMsg){
case WM_DESTROY:
closed = true;
PostQuitMessage(0);
break;
default:
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
bool Window::isClosed(){
return closed;
}
Window::~Window(){
if (hWnd && !DestroyWindow(hWnd)){
hWnd = nullptr;
}
}
private:
HWND hWnd;
bool closed;
};
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
Window win("Title", 640, 480);
MSG msg;
while(!win.isClosed()){
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
On the line closed = true; in WindowProc happens the violation.
Any ideas why?
You cast the lpCreateParams to long which throws away the top 32 bits of the pointer. This is what you should have thought about when you changed GWL_USERDATA to GWLP_USERDATA. That's why we changed the name. To force you to look at all the affected code and make corresponding changes to support 64-bit operations. (This is also something you should have noticed during debugging. "Hm, the value of this is correct except that the top 32 bits got set to zero. I wonder...")
When you call SetWindowLongPtr() you're casting the value to long which means in an x64 build you'll lose the top 32 bits.
You should cast to DWORD_PTR.