Related
I have a task to create a program which displays a list of descriptors of all windows in the system. I am getting this output:
Maybe it's wrong encoding?
Here's my code:
#include <windows.h>
ATOM RegMyWindowClass(HINSTANCE, LPCTSTR);
HWND hListBox;
HINSTANCE hin;
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
WCHAR str[255];
if (GetWindowTextW(hwnd, str, 255)) {
if (IsWindowVisible(hwnd) && (!GetWindow(hwnd, GW_OWNER)))
SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)str);
}
return 1;
}
LRESULT CALLBACK WndProc(
HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_LBUTTONUP:
MessageBox(hWnd, TEXT("Вы кликнули!"), TEXT("событие"), 0);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CREATE:
hListBox = CreateWindow("LISTBOX", "", WS_CHILD | WS_VISIBLE | LBS_NOTIFY | WS_VSCROLL,
0, 0, 400, 400, hWnd, (HMENU)1111, hin, NULL);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
LPCTSTR lpzClass = TEXT("My Window Class!");
if (!RegMyWindowClass(hInstance, lpzClass))
return 1;
RECT screen_rect;
GetWindowRect(GetDesktopWindow(), &screen_rect);
int x = screen_rect.right / 2 - 200;
int y = screen_rect.bottom / 2 - 200;
HWND hWnd = CreateWindow(lpzClass, TEXT("Window"),
WS_OVERLAPPEDWINDOW | WS_VISIBLE, x, y, 400, 400, NULL, NULL,
hInstance, NULL);
ShowWindow(hWnd, SW_SHOW);
EnumWindows(&EnumWindowsProc, 0);
if (!hWnd) return 2;
MSG msg = { 0 };
int iGetOk = 0;
while ((iGetOk = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (iGetOk == -1) return 3;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
ATOM RegMyWindowClass(HINSTANCE hInst, LPCTSTR lpzClassName)
{
WNDCLASS wcWindowClass = { 0 };
wcWindowClass.lpfnWndProc = (WNDPROC)WndProc;
wcWindowClass.style = CS_HREDRAW | CS_VREDRAW;
wcWindowClass.hInstance = hInst;
wcWindowClass.lpszClassName = lpzClassName;
wcWindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wcWindowClass.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE;
return RegisterClass(&wcWindowClass);
}
Any ideas how to fix this?
The problem is that you are compiling your project for ANSI, where TCHAR is an alias for CHAR, and are thus creating an ANSI-based ListBox, but you are sending Unicode strings to it. That is why you are seeing garbage in the output. You need to send ANSI strings to the ListBox, eg:
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
if (IsWindowVisible(hwnd) && (!GetWindow(hwnd, GW_OWNER)))
CHAR str[255] = {};
if (GetWindowTextA(hwnd, str, 255)) {
SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)str);
}
}
return TRUE;
}
Alternatively:
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
if (IsWindowVisible(hwnd) && (!GetWindow(hwnd, GW_OWNER))) {
CHAR str[255] = {};
if (IsWindowUnicode(hwnd)) {
WCHAR wstr[255] = {};
int len = GetWindowTextW(hwnd, wstr, 255);
if (len) {
len = WideCharToMultiByte(CP_ACP, 0, wstr, len+1, str, 255, NULL, NULL);
}
if (!len) {
return TRUE;
}
}
else if (!GetWindowTextA(hwnd, str, 255)) {
return TRUE;
}
SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)str);
}
return TRUE;
}
That being said, you are mixing ANSI, Unicode, and TCHAR APIs. You need to pick 1 API style and stick with it for everything, don't mix them (unless you ABSOLUTELY have to).
Since the majority of the code you have shown is already using TCHAR, then you can use TCHAR for everything (though, you really shouldn't, since TCHAR is meant for backwards compatibility with Win9x/ME which nobody uses anymore, and was intended only to help people migrate their code to Unicode. Modern code should not be using TCHAR at all):
#include <windows.h>
ATOM RegMyWindowClass(HINSTANCE, LPCTSTR);
HWND hListBox;
HINSTANCE hin;
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
if (IsWindowVisible(hwnd) && (!GetWindow(hwnd, GW_OWNER))) {
TCHAR str[255];
if (GetWindowText(hwnd, str, 255)) {
SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)str);
}
}
return TRUE;
}
LRESULT CALLBACK WndProc(
HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_LBUTTONUP:
// this is one case where it doesn't make sense to use TCHAR
MessageBoxW(hWnd, L"Вы кликнули!", L"событие", 0);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CREATE:
hListBox = CreateWindow(TEXT("LISTBOX"), TEXT(""), WS_CHILD | WS_VISIBLE | LBS_NOTIFY | WS_VSCROLL,
0, 0, 400, 400, hWnd, (HMENU)1111, hin, NULL);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
LPCTSTR lpzClass = TEXT("My Window Class!");
if (!RegMyWindowClass(hInstance, lpzClass))
return 1;
RECT screen_rect;
GetWindowRect(GetDesktopWindow(), &screen_rect);
int x = screen_rect.right / 2 - 200;
int y = screen_rect.bottom / 2 - 200;
HWND hWnd = CreateWindow(lpzClass, TEXT("Window"),
WS_OVERLAPPEDWINDOW | WS_VISIBLE, x, y, 400, 400, NULL, NULL,
hInstance, NULL);
ShowWindow(hWnd, SW_SHOW);
EnumWindows(&EnumWindowsProc, 0);
if (!hWnd) return 2;
MSG msg = { 0 };
int iGetOk = 0;
while ((iGetOk = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (iGetOk == -1) return 3;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
ATOM RegMyWindowClass(HINSTANCE hInst, LPCTSTR lpzClassName)
{
WNDCLASS wcWindowClass = { 0 };
wcWindowClass.lpfnWndProc = &WndProc;
wcWindowClass.style = CS_HREDRAW | CS_VREDRAW;
wcWindowClass.hInstance = hInst;
wcWindowClass.lpszClassName = lpzClassName;
wcWindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wcWindowClass.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE;
return RegisterClass(&wcWindowClass);
}
Otherise, use Unicode for everything:
#include <windows.h>
ATOM RegMyWindowClass(HINSTANCE, LPCWSTR);
HWND hListBox;
HINSTANCE hin;
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
if (IsWindowVisible(hwnd) && (!GetWindow(hwnd, GW_OWNER))) {
WCHAR str[255];
if (GetWindowTextW(hwnd, str, 255)) {
SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)str);
}
}
return TRUE;
}
LRESULT CALLBACK WndProc(
HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_LBUTTONUP:
MessageBoxW(hWnd, L"Вы кликнули!", L"событие", 0);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CREATE:
hListBox = CreateWindowW(L"LISTBOX", L"", WS_CHILD | WS_VISIBLE | LBS_NOTIFY | WS_VSCROLL,
0, 0, 400, 400, hWnd, (HMENU)1111, hin, NULL);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
LPCWSTR lpzClass = L"My Window Class!";
if (!RegMyWindowClass(hInstance, lpzClass))
return 1;
RECT screen_rect;
GetWindowRect(GetDesktopWindow(), &screen_rect);
int x = screen_rect.right / 2 - 200;
int y = screen_rect.bottom / 2 - 200;
HWND hWnd = CreateWindowW(lpzClass, L"Window",
WS_OVERLAPPEDWINDOW | WS_VISIBLE, x, y, 400, 400, NULL, NULL,
hInstance, NULL);
ShowWindow(hWnd, SW_SHOW);
EnumWindows(&EnumWindowsProc, 0);
if (!hWnd) return 2;
MSG msg = { 0 };
int iGetOk = 0;
while ((iGetOk = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (iGetOk == -1) return 3;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
ATOM RegMyWindowClass(HINSTANCE hInst, LPCWSTR lpzClassName)
{
WNDCLASSW wcWindowClass = { 0 };
wcWindowClass.lpfnWndProc = &WndProc;
wcWindowClass.style = CS_HREDRAW | CS_VREDRAW;
wcWindowClass.hInstance = hInst;
wcWindowClass.lpszClassName = lpzClassName;
wcWindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wcWindowClass.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE;
return RegisterClassW(&wcWindowClass);
}
Or, stick with ANSI for everything, if you need to maintain compatibility with existing code logic elsewhere in your project:
#include <windows.h>
ATOM RegMyWindowClass(HINSTANCE, LPCSTR);
HWND hListBox;
HINSTANCE hin;
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
if (IsWindowVisible(hwnd) && (!GetWindow(hwnd, GW_OWNER))) {
CHAR str[255];
if (GetWindowTextA(hwnd, str, 255)) {
SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)str);
}
}
return TRUE;
}
LRESULT CALLBACK WndProc(
HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_LBUTTONUP:
// this is one case where it doesn't make sense to use ANSI
MessageBoxW(hWnd, L"Вы кликнули!", L"событие", 0);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CREATE:
hListBox = CreateWindowA("LISTBOX", "", WS_CHILD | WS_VISIBLE | LBS_NOTIFY | WS_VSCROLL,
0, 0, 400, 400, hWnd, (HMENU)1111, hin, NULL);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
LPCSTR lpzClass = "My Window Class!";
if (!RegMyWindowClass(hInstance, lpzClass))
return 1;
RECT screen_rect;
GetWindowRect(GetDesktopWindow(), &screen_rect);
int x = screen_rect.right / 2 - 200;
int y = screen_rect.bottom / 2 - 200;
HWND hWnd = CreateWindowA(lpzClass, "Window",
WS_OVERLAPPEDWINDOW | WS_VISIBLE, x, y, 400, 400, NULL, NULL,
hInstance, NULL);
ShowWindow(hWnd, SW_SHOW);
EnumWindows(&EnumWindowsProc, 0);
if (!hWnd) return 2;
MSG msg = { 0 };
int iGetOk = 0;
while ((iGetOk = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (iGetOk == -1) return 3;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
ATOM RegMyWindowClass(HINSTANCE hInst, LPCSTR lpzClassName)
{
WNDCLASSA wcWindowClass = { 0 };
wcWindowClass.lpfnWndProc = &WndProc;
wcWindowClass.style = CS_HREDRAW | CS_VREDRAW;
wcWindowClass.hInstance = hInst;
wcWindowClass.lpszClassName = lpzClassName;
wcWindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wcWindowClass.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE;
return RegisterClassA(&wcWindowClass);
}
I code in codeblocks.
Compiler = gcc version 4.9.2 (tdm-1)
I call MessageBox in WM_COMMAND.
When I press the button, The main window stop, But the MessageBox does not show.
I'm sure the WindowProc receive the button event!
But if I create a thread, and call MessageBox in the thread function, the MessageBox will show when I press the button. But if I call MessageBox in thread, Then then MessageBox can`t stop the main window.
How I can solve this problem?
#define IDI_BUTTON_1 10001
#define IDI_BUTTON_2 10002
#ifndef UNICODE
#define UNICODE
#endif
#include "resource.h"
#include "main.h"
#include <windows.h>
#include <stdio.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR pCmdLine, int nCmdShow)
{
// Register the window class.
const wchar_t CLASS_NAME[] = L"mywindow";
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYICON));
//wc.style = CS_HREDRAW|CS_VREDRAW;
RegisterClass(&wc);
// Create the window.
HWND hwnd = CreateWindow( CLASS_NAME,
L"Mywindow",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
250,
200,
NULL,
NULL,
hInstance,
NULL
);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// Run the message loop.
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
int i;
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_CREATE:
{
HWND hwndButton1 = CreateWindow( L"button" ,L"button1",
WS_CHILD|WS_VISIBLE,
10,
10,
75,
50,
hwnd,
(HMENU)IDI_BUTTON_1,
((LPCREATESTRUCT)lParam)->hInstance,
NULL);
HWND hwndButton2 = CreateWindow( L"button" ,L"button2",
WS_CHILD|WS_VISIBLE,
120,
10,
75,
50,
hwnd,
(HMENU)IDI_BUTTON_2,
((LPCREATESTRUCT)lParam)->hInstance,
NULL);
return 0;
}
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDI_BUTTON_1:
MessageBoxW( hwnd, L"button1", L"button1", MB_ICONERROR|MB_DEFAULT_DESKTOP_ONLY );
break;
case IDI_BUTTON_2:
MessageBoxW( hwnd, L"button2", L"button2", MB_ICONERROR|MB_DEFAULT_DESKTOP_ONLY );
break;
}
return 0;
}
case WM_PAINT:
{
return 0;
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
I am trying to create an application with no visible windows, simply a tray icon. I have tried to cobble together various tutorials and answers here however haven't been able to get further than this. The context menu appears when I right click however is entirely blank. I'm also not sure how I would go about detection what I clicked on once I get it working.
The end goal is to be able to switch DNS servers by clicking one of two options in the context menu.
#include <Windows.h>
#include <shellapi.h>
#include <tchar.h>
#include <WinUser.h>
HINSTANCE gInstance = NULL;
LRESULT CALLBACK pWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wx;
HWND hWnd;
ZeroMemory(&wx, sizeof(WNDCLASSEX));
wx.cbSize = sizeof(WNDCLASSEX);
wx.lpfnWndProc = pWndProc;
wx.hInstance = hInstance;
wx.lpszClassName = (LPCWSTR)"DNSChanger";
RegisterClassEx(&wx);
CreateWindowEx(0, (LPCWSTR)"DNSChanger", (LPCWSTR)"", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
gInstance = hInstance;
MSG stMsg;
while (GetMessage(&stMsg, NULL, 0, 0) > 0)
{
TranslateMessage(&stMsg);
DispatchMessage(&stMsg);
}
return 0;
}
LRESULT CALLBACK pWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
NOTIFYICONDATA niData;
ZeroMemory(&niData, sizeof(NOTIFYICONDATA));
switch (uMsg)
{
case WM_CREATE:
{
niData.cbSize = sizeof(NOTIFYICONDATA);
niData.uID = 1;
niData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
niData.hIcon = LoadIcon(gInstance, MAKEINTRESOURCE(IDI_SHIELD));
niData.hWnd = hWnd;
niData.uCallbackMessage = WM_USER + 1;
Shell_NotifyIcon(NIM_ADD, &niData);
}
return 0;
case WM_DESTROY:
{
niData.hWnd = hWnd;
Shell_NotifyIcon(NIM_DELETE, &niData);
}
return 0;
case WM_USER + 1:
{
switch (LOWORD(lParam))
{
case WM_RBUTTONUP:
{
POINT lpClickPoint;
HMENU hPopMenu;
UINT uFlag = MF_BYPOSITION | MF_UNCHECKED | MF_STRING;
GetCursorPos(&lpClickPoint);
hPopMenu = CreatePopupMenu();
InsertMenu(hPopMenu, 0xFFFFFFFF, MF_BYPOSITION | MF_STRING, WM_USER + 1, _T("Exit"));
SetForegroundWindow(hWnd);
TrackPopupMenu(hPopMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_BOTTOMALIGN, lpClickPoint.x, lpClickPoint.y, 0, hWnd, NULL);
}
}
}
}
}
Don't use cast like this (LPCWSTR)"DNSChanger". This only hides the compiler error. The only reason your program works at all is because this error is repeated in 2 different places and it cancels out.
You meant to write L"DNSChanger".
Window procedure must return DefWindowProc(hWnd, uMsg, wParam, lParam);
In WM_DESTROY you must include PostQuitMessage(0); if you want to close the application.
Define a new constant to use in menu
const int IDM_EXIT = 100;
...
InsertMenu(hmenu, 0, MF_BYPOSITION | MF_STRING, IDM_EXIT, L"Exit");
The menu will send IDM_EXIT command as part WM_COMMAND message. Below are some recommended changes:
HINSTANCE gInstance = NULL;
const int IDM_EXIT = 100;
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static NOTIFYICONDATA niData = { sizeof(NOTIFYICONDATA) };
switch(uMsg)
{
case WM_CREATE:
{
niData.uID = 1;
niData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
niData.hIcon = LoadIcon(gInstance, IDI_SHIELD);
niData.hWnd = hWnd;
niData.uCallbackMessage = WM_USER + 1;
Shell_NotifyIcon(NIM_ADD, &niData);
return 0;
}
case WM_DESTROY:
{
niData.hWnd = hWnd;
Shell_NotifyIcon(NIM_DELETE, &niData);
PostQuitMessage(0);
return 0;
}
case WM_COMMAND:
{
if(LOWORD(wParam) == IDM_EXIT)
PostQuitMessage(0);
break;
}
case WM_USER + 1:
{
WORD cmd = LOWORD(lParam);
if (cmd == WM_RBUTTONUP || cmd == WM_LBUTTONUP)
{
POINT pt;
GetCursorPos(&pt);
HMENU hmenu = CreatePopupMenu();
InsertMenu(hmenu, 0, MF_BYPOSITION | MF_STRING, IDM_EXIT, L"Exit");
TrackPopupMenu(hmenu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_BOTTOMALIGN, pt.x, pt.y, 0, hWnd, NULL);
}
break;
}
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
{
gInstance = hInstance;
WNDCLASSEX wx = { sizeof(WNDCLASSEX) };
wx.lpfnWndProc = WndProc;
wx.hInstance = hInstance;
wx.lpszClassName = L"DNSChanger";
RegisterClassEx(&wx);
CreateWindowEx(0, L"DNSChanger", L"", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
I'm rewriting a software I wrote, because of program size and performance problems; The code compiles fine but the window doesn't show up.
I've looked into other questions about this but none solved my problem, that's why I'm asking a new question, for sake of completeness, please explain what is wrong with the code and how to solve the problem.
I'm using Visual Studio 2013.
Here's the code:
WFrame.h
#pragma once
#include <Windows.h>
#include <tchar.h>
#include <wchar.h>
class WFrame
{
public:
WFrame();
WFrame(LPCWSTR szClassName, LPCWSTR szWindowTitle, HINSTANCE hInstance, int nCmdShow, int nX, int nY, int nWidth, int nHeight, DWORD dwStyle = WS_EX_OVERLAPPEDWINDOW);
~WFrame();
void show();
static LRESULT CALLBACK staticWindowProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
virtual LRESULT CALLBACK WindowProcedure(UINT uMsg, WPARAM wParam, LPARAM lParam);
protected:
private:
HWND hWnd;
int cmdShow;
};
WFrame.cpp
#include "WFrame.h"
WFrame::WFrame()
{
}
WFrame::WFrame(LPCWSTR szClassName, LPCWSTR szWindowTitle, HINSTANCE hInstance, int nCmdShow, int nX, int nY, int nWidth, int nHeight, DWORD dwStyle)
{
WNDCLASSEX wClass;
ZeroMemory(&wClass, sizeof(WNDCLASSEX));
wClass.cbClsExtra = NULL;
wClass.cbSize = sizeof(WNDCLASSEX);
wClass.cbWndExtra = NULL;
wClass.hbrBackground = (HBRUSH)COLOR_WINDOW;
wClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wClass.hIcon = NULL;
wClass.hIconSm = NULL;
wClass.hInstance = hInstance;
wClass.lpfnWndProc = (WNDPROC) WFrame::staticWindowProcedure;
wClass.lpszClassName = szClassName;
wClass.lpszMenuName = NULL;
wClass.style = CS_HREDRAW | CS_VREDRAW;
if (!RegisterClassEx(&wClass))
{
int nResult = GetLastError();
MessageBox(NULL,
L"Window class creation failed",
L"Window Class Failed",
MB_ICONERROR);
}
this->hWnd = CreateWindow(
szClassName,
szWindowTitle,
dwStyle,
nX,
nY,
nWidth,
nHeight,
NULL,
NULL,
hInstance,
NULL);
if (!hWnd)
{
int nResult = GetLastError();
MessageBox(NULL,
L"Window creation failed",
L"Window Creation Failed",
MB_ICONERROR);
}
}
WFrame::~WFrame()
{
delete this;
}
void WFrame::show()
{
ShowWindow(this->hWnd, this->cmdShow);
UpdateWindow(this->hWnd);
}
LRESULT CALLBACK WFrame::staticWindowProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
WFrame* winptr = (WFrame*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
if (winptr == NULL) {
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
else {
return winptr->WindowProcedure(uMsg, wParam, lParam);
}
}
LRESULT CALLBACK WFrame::WindowProcedure(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CLOSE:
DestroyWindow(this->hWnd);
break;
case WM_DESTROY:
if (!GetParent(this->hWnd))
PostQuitMessage(0);
break;
}
return DefWindowProc(this->hWnd, uMsg, wParam, lParam);
}
Main.cpp
#include <Windows.h>
#include "WFrame.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WFrame * frame = new WFrame(L"Window", L"Window", hInstance, nCmdShow, 0, 0, 1024, 700);
frame->show();
MSG msg;
ZeroMemory(&msg, sizeof(MSG));
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
Thanks to further answers.
I didn't see you assign a value to member variable cmdShow, so its default value is 0, which is SW_HIDE, so you should try the code below, see if the window can show up or assign cmdShow in WFrame initializer.
void WFrame::show()
{
ShowWindow(this->hWnd, SW_SHOW);
UpdateWindow(this->hWnd);
}
You are using WS_EX_OVERLAPPEDWINDOW for the dwStyle param of CreateWindow. This flag should actually be used for the dwExStyle param of CreateWindowEx. Use WS_OVERLAPPEDWINDOW instead.
Don't forget to delete frame; when you're done. You actually don't even need a pointer here. Just instantiate frame on the stack.
Also, you should return 0; for the window messages that you handled, instead of calling DefWindowProc.
okay, so I have taken out the time to learn a but of the Win32 API to do with opening windows, and the code I came up with in the end I would think would work, but doesn't. I registered the window class, made all the things I have to, but when I run it, nothing happens... It would be a great help if someone could point out what I am doing wrong/missing.
#include <stdlib.h>
#include <iostream>
#include <Windows.h>
#pragma comment (lib, "wsock32.lib")
#define WNDCLASSNAME "wndclass"
bool quit = false;
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 nshowcmd)
{
WNDCLASSEX WCE;
WCE.cbSize = sizeof(WNDCLASSEX);
WCE.style = CS_HREDRAW|CS_VREDRAW|CS_OWNDC|CS_DBLCLKS;
WCE.lpfnWndProc = WndProc;
WCE.cbClsExtra = 0;
WCE.cbWndExtra = 0;
WCE.hInstance = hinstance;
WCE.hIcon = NULL;//LoadImage()
WCE.hCursor = NULL;//LoadCursor(NULL, IDC_CROSS);
WCE.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
WCE.lpszMenuName = NULL;
WCE.lpszClassName = "KyleWindow";
WCE.hIconSm = NULL;
RegisterClassEx(&WCE);
HWND WindowHandle;
WindowHandle = CreateWindowEx(WS_OVERLAPPEDWINDOW, "KyleWindow", "Xerus", WS_OVERLAPPEDWINDOW, 0, 0, 500, 500, NULL, NULL, hinstance, NULL);
ShowWindow(WindowHandle, SW_SHOWNORMAL);
UpdateWindow(WindowHandle);
std::cout<<"'Opened' Window"<<std::endl;
MSG msg;
while(!quit)
{
if(PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))
{
if(msg.message == WM_QUIT)
quit = true;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.lParam;
}
Use WS_EX_OVERLAPPEDWINDOW as the first parameter of your CreateWindowEx function (instead of WS_OVERLAPPEDWINDOW, which is not a valid extended window style).
instead of using WNDCLASSEX use WNDCLASS
change:
WNDCLASSEX WCE; to WNDCLASS WCE;
remove line:
WCE.cbSize = sizeof(WNDCLASSEX);
change:
RegisterClassEx(&WCE); to RegisterClass(&WCE);
The function int WINAPI WinMain must be before function LRESULT CALLBACK WndProc. Compilers read in order.