System Tray Context Menu Blank - c++

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;
}

Related

Winapi: Child window that is registered and not created gives the parent window it's background color

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.

How to open system menu in Notepad from separate program in C++?

I am trying to make the system menu in Notepad popup as seen here:
It doesn't have to be the Help menu; any menu will do.
This code brings the window to the foreground and logs 0x204a4 0x2bd041f 0 but doesn't open the menu.
#include <iostream>
#include <windows.h>
int main() {
HWND hWnd = FindWindow(NULL, "Untitled - Notepad");
SetForegroundWindow(hWnd);
HMENU hMenu = GetSystemMenu(hWnd, FALSE);
int flag = TrackPopupMenu(hMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON, 452, 335, NULL, hWnd, NULL);
std::cout << hWnd << " " << hMenu << " " << flag << std::endl; // 0x204a4 0x2bd041f 0
SendMessage(hWnd, WM_SYSCOMMAND, flag, 0);
}
g++ main.cpp
UPDATE:
Here is my updated code. It opens the wrong menu:
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR pCmdLine, int nCmdShow) {
const wchar_t CLASS_NAME[] = L"My Window Class";
WNDCLASS wc = {};
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
HWND hwnd = CreateWindowEx(0, CLASS_NAME, L"My Window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
if (hwnd == NULL) {
return 0;
}
ShowWindow(hwnd, nCmdShow);
//--------------------------------------------------------------
HWND hWndNotepad = FindWindow(NULL, L"Untitled - Notepad");
if (!hWndNotepad) {
MessageBox(hwnd, L"Notepad window handle not found.", L"Error", MB_OK | MB_ICONERROR);
}
if (!SetForegroundWindow(hWndNotepad)) {
MessageBox(hwnd, L"Unable to bring Notepad window to front.", L"Error", MB_OK | MB_ICONERROR);
}
HMENU hMenu = GetSystemMenu(hWndNotepad, FALSE);
if (!hMenu) {
MessageBox(hwnd, L"Notepad menu handle not found.", L"Error", MB_OK | MB_ICONERROR);
}
TrackPopupMenuEx(hMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON, 452, 335, hwnd, NULL);
//--------------------------------------------------------------
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) {
switch (uMsg) {
case WM_CREATE:
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
EndPaint(hwnd, &ps);
break;
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR pCmdLine, int nCmdShow) {
const wchar_t CLASS_NAME[] = L"My Window Class";
WNDCLASS wc = {};
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
HWND hwnd = CreateWindowEx(0, CLASS_NAME, L"My Window", WS_OVERLAPPEDWINDOW, 683 - 100, 360 - 150, 300, 200, NULL, NULL, hInstance, NULL);
if (hwnd == NULL) {
return 0;
}
ShowWindow(hwnd, nCmdShow);
//--------------------------------------------------------------
HWND hWndNotepad = FindWindow(NULL, L"Untitled - Notepad");
if (!hWndNotepad) {
MessageBox(hwnd, L"Notepad window handle not found.", L"Error", MB_OK | MB_ICONERROR);
return 0;
}
HMENU hMenu = GetMenu(hWndNotepad);
if (!hMenu) {
MessageBox(hwnd, L"Notepad menu handle not found.", L"Error", MB_OK | MB_ICONERROR);
return 0;
}
tagTPMPARAMS tpm_params;
tpm_params.cbSize = sizeof(tagTPMPARAMS);
GetWindowRect(hWndNotepad, &tpm_params.rcExclude);
TrackPopupMenuEx(GetSubMenu(hMenu, 0), NULL, tpm_params.rcExclude.left, tpm_params.rcExclude.top, hwnd, NULL);
//--------------------------------------------------------------
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) {
switch (uMsg) {
case WM_CREATE:
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
EndPaint(hwnd, &ps);
break;
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
g++ main.cpp -mwindows

C++ WinAPI. Wrong text display in the listbox

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);
}

MessageBox doesn't appear

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);
}

creating a window in c++

I have some experience with c++, and other languages but I've only made games before using c++ and I need to make a OBS plugin.. I was wondering if anyone could help..
I'm trying to create a window with -
int nHeight = 500;
int nWidth = 500;
#define metaData(lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)\
CreateWindowExA(0L, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)
if (GetAsyncKeyState(VK_F5))
{
//MsgeBox::myMessage::createMessage(NULL, (LPCWSTR)L"Hello", (LPCWSTR)L"I See You.", MB_ICONWARNING | MB_CANCELTRYCONTINUE);
#define CreateWindow metaData;
}
It doesn't create a window, and it doesn't give an error.. when I call the messagebox it only appears once I try to close the window.. why is that?
How could I create a seperate window?
the tutorial im following is - https://msdn.microsoft.com/en-us/library/bb384843.aspx
You have to create a message procedure then respond to key messages. For example
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case WM_KEYDOWN:
if (wp == VK_F5)
CreateWindow(L"ChildClass", L"Child window",
WS_VISIBLE | WS_POPUPWINDOW | WS_CAPTION,
0, 0, 300, 200, hwnd, 0, 0, 0);
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, msg, wp, lp);
}
Note that you have to register a second class name for "ChildClass" and then create a different message procedure for this child class.
Then you add a separate function called ChildProc which is similar to WndProc. For example:
#define UNICODE
#include <Windows.h>
HINSTANCE g_hinstance = 0;
LRESULT CALLBACK ChildProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, msg, wp, lp);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case WM_KEYDOWN:
{
if (wp == VK_F5)
{
MessageBox(0, L"VK_F5 detected", 0, 0);
if (!CreateWindow(L"ChildClass", L"ChildTitle",
WS_VISIBLE | WS_POPUPWINDOW | WS_CAPTION, 100, 100, 300, 200,
hwnd, 0, g_hinstance, 0))
{
DWORD err = GetLastError();
wchar_t buf[100];
wsprintf(buf, L"%d\n", err);
MessageBox(0, buf, 0, 0);
}
}
break;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, msg, wp, lp);
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR, int)
{
WNDCLASSEX wcex = { sizeof(WNDCLASSEX) };
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.hInstance = hInstance;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wcex.lpszClassName = L"MainClass";
RegisterClassEx(&wcex);
wcex.lpszClassName = L"ChildClass";
wcex.lpfnWndProc = ChildProc;
RegisterClassEx(&wcex);
CreateWindow(L"MainClass", L"MainTitle", WS_VISIBLE | WS_OVERLAPPEDWINDOW,
0, 0, 600, 400, 0, 0, hInstance, 0);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}