Why does clicking on edit box close win32 window(C++)? - c++

The code below should create a simple window with a menu, static text, and an edit box but When I try to create an edit box it either does not run at all (with no errors) or when it does run and I try to click on the edit box the window closes. I am really stuck and any help would be greatly appreciated! Side note: I am a beginner at winapi/gui's with c++ so please be respectful.
#include <Windows.h>
#include <iostream>
#define FILE_MENU_NEW 1
#define FILE_MENU_OPEN 2
#define FILE_MENU_EXIT 3
struct WindowPosition
{
int x, y = 0;
} winPos;
struct WindowSize
{
int width = 600;
int height = 500;
} winSize;
HMENU hMenu;
// Window proc function
LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);
void addMenus(HWND);
void AddControls(HWND);
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR args, int ncmdshow)
{
WNDCLASSW wc = { 0 };
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hInstance = hInst;
wc.lpszClassName = L"myWindowClass";
wc.lpfnWndProc = WindowProcedure;
if (!RegisterClassW(&wc))
{
return -1;
}
CreateWindowW(L"myWindowClass", L"My Window", WS_OVERLAPPEDWINDOW | WS_VISIBLE, winPos.x, winPos.y, winSize.width, winSize.height,
NULL, NULL, NULL, NULL);
// Window loop
MSG msg = { 0 };
while (GetMessage(&msg, NULL, NULL, NULL))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case WM_COMMAND:
if (wp == 1)
{
MessageBeep(MB_OK);
}
else if (FILE_MENU_EXIT)
{
DestroyWindow(hWnd);
}
break;
case WM_CREATE:
addMenus(hWnd);
AddControls(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProcW(hWnd, msg, wp, lp);
}
}
void addMenus(HWND hWnd)
{
hMenu = CreateMenu();
HMENU hFileMenu = CreateMenu();
AppendMenu(hFileMenu, MF_STRING, FILE_MENU_NEW, L"New");
AppendMenu(hFileMenu, MF_STRING, FILE_MENU_OPEN, L"Open");
AppendMenu(hFileMenu, MF_SEPARATOR, NULL, NULL);
AppendMenu(hFileMenu, MF_STRING, FILE_MENU_EXIT, L"Exit");
AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hFileMenu, L"File");
AppendMenu(hMenu, MF_STRING, 2, L"Help");
SetMenu(hWnd, hMenu);
}
void AddControls(HWND hWnd)
{
CreateWindowW(L"static", L"Username: ", WS_VISIBLE | WS_CHILD, 200, 100, 100, 50, hWnd, NULL, NULL, NULL);
// This is where the problem is... (When I remove the second parameter and put L"Enter Username") the program does not run at all.
CreateWindowW(L"edit", NULL, WS_VISIBLE | WS_CHILD, 0, 0, 100, 50, hWnd, NULL, NULL, NULL);
}

When you use else if (FILE_MENU_EXIT), this result is always true. You can try:
case WM_COMMAND:
if (wp == 1)
{
MessageBeep(MB_OK);
}
else if (wp == FILE_MENU_EXIT)
{
DestroyWindow(hWnd);
}
break;
Also you can use:
case WM_COMMAND:
switch (wp)
{
case FILE_MENU_NEW:
MessageBeep(MB_OK);
break;
case FILE_MENU_EXIT:
DestroyWindow(hWnd);
break;
}
break;

Related

win32 GUI not loading properly after adding an edit window

When I build the program in visual studio It takes a long time to build and does not display properly, during this proccess it loads and unloads lots of what appears to be dll files in the console. If I remove the one line that starts with CreateWindowW(L"EDIT" the program will run perfectly. I have read through the documentation and I cant find what is wrong with it. Any help is appreciated.
Here is full code
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
#include<iostream>
#define file_menu_new 1
#define help_menu 2
#define file_menu_open 3
#define file_menu_exit 4
void AddMenus(HWND hwind);
HMENU hMenu;
void AddControls(HWND hwnd);
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,_In_ PSTR szCmdLine, _In_ int iCmdShow)
{
// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
//regesters class above with operateing system
RegisterClass(&wc);
// Create the window.
HWND hwnd = CreateWindowEx(
0, // Optional window styles.
CLASS_NAME, // Window class
L"Learn to Program Windows", // Window text
WS_OVERLAPPEDWINDOW | WS_VISIBLE, // Window style
// Size and position
500, 200, 800, 500,//WS_DEFAULT OR SOMETHING LIKE THAT
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, iCmdShow);
// 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)
{
switch (uMsg)
{
case WM_COMMAND:
{
switch (wParam)
{
case file_menu_new:
MessageBeep(MB_OK);//this creates a sound
break;
case file_menu_exit:
DestroyWindow(hwnd);
break;
case file_menu_open:
MessageBeep(MB_ICONINFORMATION);
default:
break;
}
}
case WM_CREATE:
{
AddControls(hwnd);
AddMenus(hwnd);
break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
EndPaint(hwnd, &ps);
break;
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
void AddMenus(HWND hwind)
{
hMenu = CreateMenu();//main menu bar
HMENU hFileMenu = CreateMenu();//this is a drop down menu for the file part of main menu
//AppendMenu(hMenu, MF_STRING, 1, L"File");//1 is the identity of this main menu
AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hFileMenu, L"File");//this is how you make it pop up another menu
AppendMenu(hFileMenu, MF_STRING, file_menu_new, L"New");//adds stuff to hFileMenu with the id of 1
AppendMenu(hFileMenu, MF_STRING, file_menu_open, L"Open");//adds stuff to hFileMenu with the id of 3
AppendMenu(hFileMenu, IMFT_SEPARATOR, NULL, NULL);//creates a seperator or a line under open
AppendMenu(hFileMenu, MF_STRING, file_menu_exit, L"Exit");
AppendMenu(hMenu, MF_STRING, help_menu, L"Help");//2 is the identity of this main menu
//sets the hMenu to the hwind menu or the main menu
SetMenu(hwind, hMenu);
}
void AddControls(HWND hwnd)
{
CreateWindowW(L"static", L"Enter Text here: ", WS_VISIBLE | WS_CHILD | WS_BORDER | SS_CENTER | WS_EX_TRANSPARENT,
200, 100, 100, 50, hwnd, NULL, NULL, NULL);
CreateWindowW(L"EDIT", L"Enter Text here: ", WS_VISIBLE | WS_CHILD | WS_BORDER | SS_CENTER,
200, 160, 100, 50, hwnd, NULL, NULL, NULL);
}
Add wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); and remove WM_PAINT. If you don't set a class background you need to handle WM_ERASEBKGND or otherwise validate the background color painting.

WinAPI menu doesn't appear after adding edit control

I am learning how to use WinAPI with C++, and am creating an application which at the moment just has a basic edit control for someone to enter their username.
void AddMenus(HWND hWnd)
{
hMenu = CreateMenu();
hSubMenu = CreateMenu();
AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hSubMenu, L"File");
AppendMenu(hSubMenu, MF_STRING, FILE_MENU_EXIT, L"Exit");
SetMenu(hWnd, hMenu);
}
void AddControls(HWND hWnd)
{
hUNameS = CreateWindowW(L"static", L"Username: ", WS_VISIBLE | WS_CHILD | ES_CENTER,
100, 50, 100, 25, hWnd, NULL, NULL, NULL);
hUName = CreateWindowW(L"edit", L" ", WS_VISIBLE | WS_CHILD | WS_BORDER,
202, 50, 100, 25, hWnd, NULL, NULL, NULL);
}
When using the following block of code to create the window, both the controls and the menu don't appear.
case WM_CREATE:
AddControls(hWnd);
AddMenus(hWnd);
break;
If I comment out the AddControls, then the menu appears fine, but if I leave them both as shown, then the menu doesn't appear. Nothing changes if I swap the order of the function calls.
Both the menu and the controls appear if I set the second parameter of the edit control to NULL, but then I get a different problem, where any text I type in the control is invisible until I click it, and then disappears again when I continue to type. The only way I have found to fix this is by having a placeholder which then removes the menu.
TLDR: I can't get both the menu and controls to appear at the same time, and without the second parameter of the edit control being set, then text is invisible to start with.
The code of your first question:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case FILE_MENU_DESTROY:
{
DestroyWindow(hWnd);
break;
}
case FILE_MENU_ABOUT:
{
MessageBox(hWnd, L"about", L"About", MB_OK);
break;
}
break; //this break will not break outside case WM_COMMAND, but only break outside the switch (wmId).
}
}
case WM_CREATE:
AddControls(hWnd);
AddMenus(hWnd);
break;
...
}
need to move the break; above the WM_CREATE to break WM_COMMAND case. Otherwise, when you createwindow and receive WM_COMMAND, WinMenu(AddMenus for this case) will be executed multiple times. I can reproduce with this code.
Modify to:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case FILE_MENU_DESTROY:
{
DestroyWindow(hWnd);
break;
}
case FILE_MENU_ABOUT:
{
MessageBox(hWnd, L"about", L"About", MB_OK);
break;
}
}
}
break;
case WM_CREATE:
AddControls(hWnd);
AddMenus(hWnd);
break;
...
}
This works for me, and the whole project:
#define MAX_LOADSTRING 100
#define FILE_MENU_DESTROY 1
#define FILE_MENU_ABOUT 2
// Global Variables:
HINSTANCE hInst; // current instance
WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
//Custom Application Function Forwrd Declarations
void WinControls(HWND);
void WinMenu(HWND);
HMENU hMenu;
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
// Initialize global strings
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_RANKTOOLADVANCED, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance); //Generates an instance of a window class
// Perform application initialization:
if (!InitInstance(hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_RANKTOOLADVANCED));
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
ATOM MyRegisterClass(HINSTANCE hInstance)//Class properties of the window
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc; //assigns a window to the instance of the class
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance; //creates an instance
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_RANKTOOLADVANCED));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); //defines a type of cursor (arrow, help, cross, etc.)
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_RANKTOOLADVANCED);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{//initializes instance of window class (invocation)
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindowW(szWindowClass, L"test", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, 900, 600, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
void AddMenus(HWND hWnd)
{
hMenu = CreateMenu();
HMENU hSubMenu = CreateMenu();
AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hSubMenu, L"File");
AppendMenu(hSubMenu, MF_STRING, FILE_MENU_DESTROY, L"Exit");
SetMenu(hWnd, hMenu);
}
void AddControls(HWND hWnd)
{
HWND hUNameS = CreateWindowW(L"static", L"Username: ", WS_VISIBLE | WS_CHILD | ES_CENTER,
100, 50, 100, 25, hWnd, NULL, NULL, NULL);
HWND hUName = CreateWindowW(L"edit", L" ", WS_VISIBLE | WS_CHILD | WS_BORDER,
202, 50, 100, 25, hWnd, NULL, NULL, NULL);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{/*
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
case FILE_MENU_NEW:
{
MessageBox(hWnd, L"task failed successfully", L"you done goofed", MB_OK | MB_ICONEXCLAMATION);
break;
}*/
case FILE_MENU_DESTROY:
{
DestroyWindow(hWnd);
break;
}
case FILE_MENU_ABOUT:
{
MessageBox(hWnd, L"about", L"About", MB_OK);
break;
}
}
}
break;
case WM_CREATE:
AddControls(hWnd);
AddMenus(hWnd);
break;
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

Change button colors

I want to change button colors when the user click on it.
The main plan is: every month 10th one worker's button go to red and if the worker done his job then click on the button and it going to be green.
I have no idea what to do.
I already have this code. I just created a window and add a button to it:
switch (msg) {
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CREATE:
AddButton(hWnd);
break;
default:
return DefWindowProcW(hWnd, msg, wp, lp);
}
}
void AddButton(HWND hWnd)
{
CreateWindowW(L"Button", L"Change colors", WS_VISIBLE | WS_CHILD,
350, 200,
100, 100,
hWnd,
NULL,
NULL,
NULL);
}
So I tried WM_LBUTTONDOWN. I think this is something when the user click on the button the program will do something. I put in the switch(msg) case WM_LBUTTONDOWN:.
But no idea what's next.
Here is a simple demo to show how to detect click on a button, and change the color of button when you click on it.
#pragma comment(linker, "/manifestdependency:\"type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' \
publicKeyToken='6595b64144ccf1df' language='*'\"")
#pragma comment(lib, "comctl32.lib")
#include "stdafx.h"
#include <windows.h>
#include <commctrl.h>
static BOOL flag = false;
ATOM RegisterWndClass(HINSTANCE hInst);
BOOL CreateMainWnd(HINSTANCE hInstance, int nCmdShow);
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
HINSTANCE hInst;
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hInstPrev, LPWSTR lpszCmdLine,
int nCmdShow)
{
INITCOMMONCONTROLSEX icex = { 0 };
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC = ICC_LISTVIEW_CLASSES | ICC_USEREX_CLASSES | ICC_BAR_CLASSES |
ICC_COOL_CLASSES | ICC_TAB_CLASSES | ICC_WIN95_CLASSES |
ICC_PROGRESS_CLASS | ICC_PAGESCROLLER_CLASS;
InitCommonControlsEx(&icex);
MSG msg;
hInst = hInstance;
if (!RegisterWndClass(hInstance))
return NULL;
if (!CreateMainWnd(hInstance, nCmdShow))
return NULL;
while (GetMessage(&msg, NULL, NULL, NULL))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
};
ATOM RegisterWndClass(HINSTANCE hInstance)
{
WNDCLASS wndClass = { 0 };
wndClass.style = CS_DBLCLKS;
wndClass.lpfnWndProc = MainWndProc;
wndClass.hInstance = hInstance;
wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = L"MainClass";
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
return RegisterClass(&wndClass);
}
BOOL CreateMainWnd(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd = CreateWindow(L"MainClass", L"Buttons sample",
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
GetSystemMetrics(SM_CXSCREEN) / 2 - 115,
GetSystemMetrics(SM_CYSCREEN) / 2 - 50,
230, 100, NULL, NULL, hInstance, NULL);
if (!hWnd)
return FALSE;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
HBITMAP hBitmap = NULL;
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
{
// Owner draw button
CreateWindow(L"BUTTON", L"", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON |
BS_OWNERDRAW, 10, 10, 60, 30, hWnd,
(HMENU)10001, hInst, NULL);
// Custom draw button
CreateWindow(L"BUTTON", L"", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 80,
10, 60, 30, hWnd, (HMENU)10002, hInst, NULL);
// Bitmap button
HWND hBitmapButton = CreateWindow(L"BUTTON", L"", WS_CHILD | WS_VISIBLE
| BS_PUSHBUTTON | BS_BITMAP,
150, 10, 60, 30, hWnd,
(HMENU)10003, hInst, NULL);
HDC hDC = GetDC(hWnd);
HDC hMemDC = CreateCompatibleDC(hDC);
hBitmap = CreateCompatibleBitmap(hDC, 55, 25);
SelectObject(hMemDC, hBitmap);
SetDCBrushColor(hMemDC, RGB(0, 0, 255));
RECT r = { 0 };
r.left = 0;
r.right = 55;
r.top = 0;
r.bottom = 25;
FillRect(hMemDC, &r, (HBRUSH)GetStockObject(DC_BRUSH));
DeleteDC(hMemDC);
ReleaseDC(hWnd, hDC);
SendMessage(hBitmapButton, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP,
(LPARAM)hBitmap);
return 0;
}
case WM_COMMAND:
switch (LOWORD(wParam))
{
case 10001:
MessageBox(hWnd, L"Owner draw button clicked", L"Message", NULL);
return 0;
case 10002:
MessageBox(hWnd, L"Custom draw button clicked", L"Message", NULL);
return 0;
case 10003:
MessageBox(hWnd, L"Bitmap button clicked", L"Message", NULL);
return 0;
}
break;
// Owner draw button
case WM_DRAWITEM:
if (wParam == 10001)
{
if (flag == false)
{
LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT)lParam;
SetDCBrushColor(lpDIS->hDC, RGB(255, 0, 0));
SelectObject(lpDIS->hDC, GetStockObject(DC_BRUSH));
RoundRect(lpDIS->hDC, lpDIS->rcItem.left, lpDIS->rcItem.top,
lpDIS->rcItem.right, lpDIS->rcItem.bottom, 5, 5);
}
else
{
LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT)lParam;
SetDCBrushColor(lpDIS->hDC, RGB(0, 255, 0));
SelectObject(lpDIS->hDC, GetStockObject(DC_BRUSH));
RoundRect(lpDIS->hDC, lpDIS->rcItem.left, lpDIS->rcItem.top,
lpDIS->rcItem.right, lpDIS->rcItem.bottom, 5, 5);
}
flag = !flag;
return TRUE;
}
break;
// Custom draw button
case WM_NOTIFY:
switch (((LPNMHDR)lParam)->code)
{
case NM_CUSTOMDRAW:
if (((LPNMHDR)lParam)->idFrom == 10002)
{
LPNMCUSTOMDRAW lpnmCD = (LPNMCUSTOMDRAW)lParam;
switch (lpnmCD->dwDrawStage)
{
case CDDS_PREPAINT:
SetDCBrushColor(lpnmCD->hdc, RGB(0, 255, 0));
SetDCPenColor(lpnmCD->hdc, RGB(0, 255, 0));
SelectObject(lpnmCD->hdc, GetStockObject(DC_BRUSH));
SelectObject(lpnmCD->hdc, GetStockObject(DC_PEN));
RoundRect(lpnmCD->hdc, lpnmCD->rc.left + 3,
lpnmCD->rc.top + 3,
lpnmCD->rc.right - 3,
lpnmCD->rc.bottom - 3, 5, 5);
return TRUE;
}
}
break;
}
break;
case WM_DESTROY:
if (hBitmap != NULL)
DeleteObject((HBITMAP)hBitmap);
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
Try to make some modifications to "if" conditions to meet your needs.

Edit control doesn't work correctly

I started to learning winapi c++ today. And i wrote this simple program that have to change window name to the name that i write in text box:
#include <Windows.h>
LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);
void AddMenu(HWND);
void AddControl(HWND);
HWND hEdit;
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrewInst, LPSTR args, int ncmdshow)
{
WNDCLASSW wc = { 0 };
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hInstance = hInst;
wc.lpszClassName = L"class";
wc.lpfnWndProc = WindowProcedure;
if (!RegisterClassW(&wc))
return -1;
CreateWindowW(L"class", L"Window", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 500, 500, NULL, NULL, NULL, NULL);
MSG msg = { 0 };
while (GetMessage(&msg, NULL, NULL, NULL))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case WM_COMMAND:
switch (wp)
{
case 1:
MessageBeep(MB_SERVICE_NOTIFICATION); break;
case 2:
DestroyWindow(hWnd); break;
case 3:
wchar_t text[100];
GetWindowTextW(hEdit, text, 100);
SetWindowTextW(hWnd, text);
break;
}
case WM_CREATE:
AddMenu(hWnd);
AddControl(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProcW(hWnd, msg, wp, lp);
}
}
void AddMenu(HWND hWnd)
{
HMENU hMenu;
hMenu = CreateMenu();
HMENU file;
file = CreateMenu();
HMENU Sub;
Sub = CreateMenu();
AppendMenu(hMenu, MF_POPUP, (UINT_PTR)file, "File");
AppendMenu(file, MF_STRING, 1, "Open");
AppendMenu(file, MF_POPUP, (UINT_PTR)Sub, "Sub");
AppendMenu(file, MF_STRING, 2, "Exit");
AppendMenu(Sub, MF_STRING, 3, "Change");
SetMenu(hWnd, hMenu);
}
void AddControl(HWND hWnd)
{
CreateWindowW(L"Static", L"Enter text: ", WS_VISIBLE | WS_CHILD | WS_BORDER | SS_CENTER, 200, 100, 100, 20, hWnd, NULL, NULL, NULL);
hEdit = CreateWindowW(L"Edit", L"...", WS_VISIBLE | WS_CHILD | WS_BORDER | ES_MULTILINE | ES_AUTOVSCROLL, 200, 152, 100, 50, hWnd, NULL, NULL, NULL);
}
By default in text box i have .... So i run my program, starting to type hello world for expample but nothing changes. I highlited my 3 dots that had to change and boom, my text appeared. I go to the menu choose File -> Sub -> Change and my window name changes to 3 dots ....
BUT! If i delete these: | ES_MULTILINE | ES_AUTOVSCROLL then text box working correctly but menu doesnt show up in my window.
I found that i have to do smth with EN_CHANGE but idk what. I tried to change WM_COMMAND to EN_CHANGE and my textbox worked correctly, but other menu buttons didnt work at all...
Your failure is caused by handling all the edit control notifications the same way. You need to test the notification code (found in HIWORD(wParam)) to see whether it is EN_CHANGE, and let notifications you aren't handling pass through to DefWindowProc.
You also have an even bigger bug in that you reach the closing brace of a function with a non-void return type. You need to always return something; when you aren't calling DefWindowProc the system still expects a return value. The reason things start working when you change WM_COMMAND to EN_CHANGE is not because you are handling EN_CHANGE, it is because you no longer have incorrect handling of WM_COMMAND, and instead let the DefWindowProc take them.
The fall-through from WM_COMMAND into WM_CREATE isn't helping things either.
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_COMMAND:
switch (HIWORD(wParam)) /* command kind */
{
case 0: // menus
switch (LOWORD(wParam)) /* child ID */
{
case 1:
MessageBeep(MB_SERVICE_NOTIFICATION);
return 0;
case 2:
DestroyWindow(hWnd);
return 0;
case 3:
wchar_t text[100];
GetWindowTextW(hEdit, text, 100);
SetWindowTextW(hWnd, text);
return 0;
}
break;
}
break;
case WM_CREATE:
AddMenu(hWnd);
AddControl(hWnd);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
// break actions also reach here
return DefWindowProcW(hWnd, msg, wParam, lParam);
}

System Tray Context Menu Blank

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