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.
Related
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;
I'm beginner in WINAPI and I would like to ask you about help. I have main window with about 10 child's windows (edit boxes). I need click into 1 of them and see label (text) in another static box. The problem is that text is changed, the old text from previous action is drawn in the backround as you can see...
It is still overdrafted until the main window is redrawed...
I think it is not efficient to redraw main window each text change...
Does anyone have experiance with this problem?
Could you help me?
Thank you very much!
void vytvor_edit(HWND* h_edit,unsigned short ID)
{
*h_edit = CreateWindowEx(WS_EX_CLIENTEDGE,
WC_EDIT,
NULL,
WS_CHILD | WS_VISIBLE | ES_LEFT | ((ID_MINDISP != ID)?ES_NUMBER:0),
0, 0, 200, 25,
h_hlavni,
(HMENU)ID,
GetModuleHandle(NULL),
NULL);
if (*h_edit == NULL)
FatalAppExit(0, L"nepovedlo se vytvorit ovladani");
HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
SendMessage(*h_edit, WM_SETFONT, (WPARAM)hFont, (LPARAM)TRUE);
oldProc = (WNDPROC)SetWindowLongPtr(*h_edit,
GWLP_WNDPROC, (LONG_PTR)WindowProcEdit);
}
void vytvor_combo(HWND* h_combo,unsigned short ID)
{
*h_combo = CreateWindowEx(WS_EX_CLIENTEDGE,
WC_COMBOBOX,
NULL,
WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS,
0, 0, 200, 250,
h_hlavni,
(HMENU)ID,
GetModuleHandle(NULL),
NULL);
if (*h_combo == NULL)
FatalAppExit(0, L"nepovedlo se vytvorit ovladani");
HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
SendMessage(*h_combo, WM_SETFONT, (WPARAM)hFont, (LPARAM)TRUE);
/*oldProc = (WNDPROC)SetWindowLongPtr(*h_edit,
GWLP_WNDPROC, (LONG_PTR)WindowProcEdit);*/
}
void vytvor_button(HWND hwnd, HWND* h_button,const wchar_t* nazev,HMENU proces)
{
*h_button = CreateWindowEx(WS_EX_CLIENTEDGE,
WC_BUTTON,
nazev,
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
0, 0, 200, 50,
hwnd,
proces,
GetModuleHandle(NULL),
NULL);
if (*h_button == NULL)
FatalAppExit(0, L"nepovedlo se vytvorit ovladani");
HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
SendMessage(*h_button, WM_SETFONT, (WPARAM)hFont, (LPARAM)TRUE);
/*oldProc = (WNDPROC)SetWindowLongPtr(*h_edit,
GWLP_WNDPROC, (LONG_PTR)WindowProcEdit);*/
}
void vytvor_button_kalibrace(HWND hwnd, HWND* h_button, HMENU proces)
{
*h_button = CreateWindowEx(WS_EX_CLIENTEDGE,
WC_BUTTON,
NULL,
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_OWNERDRAW,
0, 0, 200, 200,
hwnd,
proces,
GetModuleHandle(NULL),
NULL);
if (*h_button == NULL)
FatalAppExit(0, L"nepovedlo se vytvorit ovladani");
HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
SendMessage(*h_button, WM_SETFONT, (WPARAM)hFont, (LPARAM)TRUE);
}
void vytvor_static(HWND* h_edit, unsigned short ID)
{
*h_edit = CreateWindowEx(WS_EX_CLIENTEDGE,
WC_STATIC,
L"Info text",
WS_CHILD | WS_VISIBLE | SS_SIMPLE,
0, 0, 200, 25,
h_hlavni,
(HMENU)ID,
GetModuleHandle(NULL),
NULL);
if (*h_edit == NULL)
FatalAppExit(0, L"nepovedlo se vytvorit ovladani");
HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
SendMessage(*h_edit, WM_SETFONT, (WPARAM)hFont, (LPARAM)TRUE);
}
wm_paint
void wm_paint(HWND hwnd) noexcept
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
Gdiplus::Graphics* g = new Gdiplus::Graphics(hdc);
RECT rect;
GetClientRect(hwnd, &rect);
g->DrawImage(pBitMapL, rect.right/12, 2, rect.right / 3 , rect.bottom - vyska_ovladani);
g->DrawImage(pBitMapR, (rect.right*7)/12, 2, rect.right / 3, rect.bottom - vyska_ovladani);
if (pBitDisp != NULL)
g->DrawImage(pBitDisp, rect.right / 2, rect.bottom - vyska_ovladani+4, rect.right / 2 - 4, vyska_ovladani-10);
g->DrawImage(pBitDisp, rect.right / 2, rect.bottom - vyska_ovladani + 4, rect.right / 2 - 4, vyska_ovladani - 10);
EndPaint(hwnd, &ps);
delete g;
}
and the rest
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DISPARITYLADIC));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_DISPARITYLADIC);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
//
// FUNKCE: InitInstance(HINSTANCE, int)
//
// ÚČEL: Uloží popisovač instance a vytvoří hlavní okno.
//
// KOMENTÁŘE:
//
// V této funkci uložíme popisovač instance do globální proměnné
// a vytvoříme a zobrazíme hlavní okno programu.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Uloží popisovač instance do naší globální proměnné.
h_hlavni = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
if (!h_hlavni)
{
return FALSE;
}
vytvorit_ovladani();
ShowWindow(h_hlavni, SW_MAXIMIZE);
UpdateWindow(h_hlavni);
return TRUE;
}
//
// FUNKCE: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// ÚČEL: Zpracuje zprávy pro hlavní okno.
//
// WM_COMMAND - zpracování aplikační nabídky
// WM_PAINT - Vykreslení hlavního okna
// WM_DESTROY - vystavení zprávy o ukončení a návrat
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Analyzovat vybrané možnosti nabídky:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
SendMessage(hWnd, WM_CLOSE, 0, 0);
break;
case ID_SPOCITEJ:
{
SendMessage(hWnd, WM_PAINT, 0, 0);
HANDLE h = (HANDLE)_beginthreadex(NULL, 0, vlakno_zpracovani, 0, NULL, NULL);
CloseHandle(h);
}
break;
case ID_NACTIKALIBRACI:
nacti_kalibraci();
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
wm_paint(hWnd);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_SIZE:
posun_ovladani(hWnd);
break;
case WM_DRAWITEM:
on_drawitem((DRAWITEMSTRUCT*)lParam);
break;
case WM_CLOSE:
if (MessageBox(hWnd, L"probiha vypocet...chcete ukoncit?", L"Upozorneni", MB_YESNOCANCEL | MB_ICONQUESTION) == IDYES)
return DefWindowProc(hWnd, message, wParam, lParam);
else
return 0;
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam); }
return 0;
}
LRESULT CALLBACK WindowProcEdit(HWND hWnd, UINT uMsg,
WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_GETDLGCODE:
return DLGC_WANTALLKEYS;
case WM_SETFOCUS:
unsigned int id =(unsigned int) GetMenu(hWnd);
switch (id)
{
case ID_BLOCKSIZE:
RECT rec;
GetClientRect(h_static_infotext, &rec);
BOOL ano;
SetWindowText(h_static_infotext, L"BLOCK SIZE");
RedrawWindow(h_static_infotext, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE );
break;
case ID_DISPMAXDIFF:
SetWindowText(h_static_infotext, L"DISPARITY ROZDIL");
RedrawWindow(h_static_infotext, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
break;
case ID_FILTERCAP:
SetWindowText(h_static_infotext, L"FILTER CAP");
RedrawWindow(h_static_infotext, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
break;
case ID_MINDISP:
SetWindowText(h_static_infotext, L"MIN DISPARITY");
RedrawWindow(h_static_infotext, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
break;
case ID_MODE:
SetWindowText(h_static_infotext, L"MODE");
RedrawWindow(h_static_infotext, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
break;
case ID_NUMDISP:
SetWindowText(h_static_infotext, L"HODNOTA DISPARITY");
RedrawWindow(h_static_infotext, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
break;
case ID_P1:
SetWindowText(h_static_infotext, L"HODNOTA P1");
RedrawWindow(h_static_infotext, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
break;
case ID_P2:
SetWindowText(h_static_infotext, L"HODNOTA P2");
RedrawWindow(h_static_infotext, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
break;
case ID_SPECKLERANGE:
SetWindowText(h_static_infotext, L"SPECKLE ROZSAH");
RedrawWindow(h_static_infotext, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
break;
case ID_SPECKLESIZE:
SetWindowText(h_static_infotext, L"SPECKLE VELIKOST");
RedrawWindow(h_static_infotext, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
break;
case ID_UNIQRATIO:
SetWindowText(h_static_infotext, L"UNIQ RATIO");
RedrawWindow(h_static_infotext, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);
break;
default:
break;
}
break;
}
return CallWindowProc(oldProc, hWnd, uMsg, wParam, lParam);
}
// Obslužná rutina zprávy pro pole O produktu
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
The problem is that Microsoft never anticipated the text in a static control changing, so they didn't implement a proper WM_ERASE to erase the static background. You can subclass the control and do it yourself, or you can draw over the static control a rectangle of the background color before changing the text.
I'm trying to make button change background color of window when clicked. I know that I need to handle this event in WM_COMMAND, where I also check ID of this button, but nothing happens. I tried to debug and my program recognizes ID correctly. The piece of code used for changing color works well when in main loop but it doesn't do anything when in WM_COMMAND. How do I solve this problem? Whole code:
#include <Windows.h>
#define BUTTON_ID 100
struct status_info {
const char* waiting = "Waiting for connection...";
const char* connected = "Connected.\nWaiting for frajer to copy number.";
const char* changed = "Number changed.";
}status_info;
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow) {
const wchar_t CLASS_NAME[] = L"Name";
WNDCLASS wc = {};
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = (LPCSTR)CLASS_NAME;
wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
RegisterClass(&wc);
//main window
HWND hwnd = CreateWindowEx(0, (LPCSTR)CLASS_NAME, (LPCSTR)"Hacker", WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 500, 300, NULL, NULL, hInstance, NULL);
//number window
HWND number = CreateWindowEx(WS_EX_WINDOWEDGE, TEXT("Static"), TEXT("Account number:\n00 1234 1234 1234 1234 1234 1234"), WS_CHILD | WS_VISIBLE, 5, 5, 240, 40, hwnd, NULL, NULL, NULL);
//status window
const char* status_message = status_info.waiting;
HWND status = CreateWindowEx(WS_EX_WINDOWEDGE, TEXT("Static"), TEXT(status_message), WS_CHILD | WS_VISIBLE, 5, 55, 240, 40, hwnd, NULL, NULL, NULL);
//button
HWND button = CreateWindowEx(0, "BUTTON", "Nightmode", WS_CHILD | WS_VISIBLE, 100, 100, 150, 30, hwnd, (HMENU)BUTTON_ID, hInstance, NULL);
MSG msg;
WNDCLASS okno;
while (GetMessage(&msg, (HWND)NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
SetWindowText(status, status_message);
}
return msg.wParam;
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
//MessageBox(hwnd, L"1", L"1", 0);
return (0);
case WM_DESTROY:
//MessageBox(hwnd, L"2", L"2", 0);
PostQuitMessage(0);
return (0);
case WM_COMMAND: {
if (LOWORD(wParam) == BUTTON_ID) {
PAINTSTRUCT ps;
RECT rc;
HDC hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rc);
SetBkColor(hdc, BLACK_BRUSH);
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, 0, 0, 0);
EndPaint(hwnd, &ps);
}
break;
}
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
}
BeginPaint/EndPaint should be used in response to WM_PAINT only.
You can use GetDC(hwnd)/ReleaseDC(hwnd, hdc) to obtain hdc for painting on device context outside of WM_PAINT, but this will be temporary. The next refresh message causes the window to be erased and repainted according to what's in WM_PAINT
SetDCBrushColor can be used if the goal is to avoid creating brush handle.
static COLORREF bkcolor = RGB(255,255,255);
switch(message)
{
case WM_COMMAND:
if(LOWORD(wparam) == BUTTON_ID)
{
bkcolor = RGB(255, 0, 0);
InvalidateRect(hwnd, NULL, TRUE);
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
RECT rc;
HDC hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rc);
SetDCBrushColor(hdc, bkcolor);
FillRect(hdc, &rc, (HBRUSH)GetStockObject(DC_BRUSH));
//or use ps.rcPaint to repaint only the section which requires update
//FillRect(hdc, &ps.rcPaint, (HBRUSH)GetStockObject(DC_BRUSH));
EndPaint(hwnd, &ps);
return 0;
}
case WM_ERASEBKGND:
//return 0 means WM_PAINT handles the background
return 0;
Alternatively, use SetClassLongPtr to replace the background brush:
static HBRUSH bkbrush = NULL;
switch(message)
{
case WM_COMMAND:
if(LOWORD(wparam) == BUTTON_ID)
{
COLORREF bkcolor = RGB(rand() % 256, rand() % 256, rand() % 256);
if(bkbrush)
DeleteObject(bkbrush);
bkbrush = CreateSolidBrush(bkcolor);
SetClassLongPtr(hwnd, GCL_HBRBACKGROUND, (LONG)bkbrush);
InvalidateRect(hwnd, NULL, TRUE);
}
break;
Alright so this code is pretty long over a short problem so I will kinda use <--- arrows to point it out for you, but down in my switch case WM_COMMAND:
I am kinda confused on using the return 0/ break.
return 0; seems to jump me outside of the whole WndProc function (skips over some code)
break; just breaks out of the switch statement but continues.
So does that mean I should use return 0; at the very end of my switch statement to prevent from moving on? Or is there something just wrong with my WM_MAXMININFO, because I never had that problem until after I changed the return 0 to break; The reason I ask is because once it hits WM_MAXMININFO I get a Access Violation. (That may be that cause of all of this).
// Win32Project2.cpp : Defines the entry point for the application.
#include "stdafx.h"
#include "Win32Project2.h"
#include <Windows.h>
#include <Windowsx.h>
#include <shellapi.h>
#include "ProcessFind.h"
#include <WinUser.h>
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#define BUTTON L"button"
#define szDefault L"Awaiting Commands..."
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdShow, int iCmdLine)
{
wchar_t szAppName[] = L"Game Launcher";
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hInstance = hInstance;
wndclass.lpszClassName = szAppName;
wndclass.lpszMenuName = NULL;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wndclass);
hwnd = CreateWindow(szAppName, L"GameLauncher v1.0", WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, 375, 100, NULL, NULL, hInstance, 0);
ShowWindow(hwnd, iCmdLine);
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 hUserBox;
static HWND hWindowButton;
HBITMAP hImage = (HBITMAP)LoadImage(NULL, L"?C:\\Users\\chaos\\Desktop\\Capture.PNG", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_LOADTRANSPARENT);
switch (message)
{
case WM_CREATE:
CreateWindowEx(NULL, BUTTON, L"Check for process", WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX , 5, 35, 150, 25, hwnd, (HMENU)2, NULL, NULL);
CreateWindow(BUTTON, L"Minecraft", WS_CHILD | WS_VISIBLE, 250, 5, 100, 25, hwnd, (HMENU)1, NULL, NULL);
CreateWindow(BUTTON, L"Options", WS_CHILD | WS_VISIBLE | WS_DISABLED, 250, 30, 100, 25, hwnd, (HMENU)3, NULL, NULL);
hUserBox = CreateWindow(L"static", L"Awaiting Commands...", WS_CHILD | WS_VISIBLE | WS_BORDER, 5, 5, 240, 25, hwnd, (HMENU) 2, NULL, NULL);
return 0;
case WM_COMMAND:
switch (LOWORD(wparam))
{
case 1:
{
wchar_t* szProccessToKill = new wchar_t[20];
GetWindowText(hUserBox, szProccessToKill, 20);
// Checking checked status on checkbox. (Say that 5 times fast lol)
if (IsDlgButtonChecked(hwnd, 2) == BST_CHECKED)
{
ProcessFind testFunction;
SetWindowText(hUserBox, L"Ending process");
Sleep(1000);
testFunction.EndProcess(L"java.exe");
SetWindowText(hUserBox, L"Launching Minecraft...");
Sleep(1000);
ShellExecute(NULL, L"open", L"MinecraftLauncher", NULL, L"C:\\Program Files (x86)\\Minecraft", 6);
SetWindowText(hUserBox, L"Minecraft has launched sucessfully!");
Sleep(1000);
SetWindowText(hUserBox, szDefault);
}
else if (IsDlgButtonChecked(hwnd, 2) == BST_UNCHECKED)
{
SetWindowText(hUserBox, L"Launching Minecraft...");
HINSTANCE ErrorCode = ShellExecute(NULL, L"open", L"C:\\Program Files (x86)\\Minecraft\\MinecraftLauncher", NULL, NULL, 1);
int ErrorCodeInt = (int)ErrorCode;
switch (ErrorCodeInt)
{
case 0:
MessageBox(NULL, L"The operating system is out of memory or resources.", L"Error", MB_OK | MB_ICONERROR);
break;
case ERROR_FILE_NOT_FOUND:
MessageBox(NULL, L"The specified file was not found.", L"Error", MB_OK | MB_ICONERROR);
break;
case ERROR_PATH_NOT_FOUND:
MessageBox(NULL, L"The specified path was not found.", L"Error", MB_OK | MB_ICONERROR);
break;
default:
SetWindowText(hUserBox, L"Minecraft has launched successfully");
Sleep(1500);
break;
}
SetWindowText(hUserBox, szDefault);
}
delete[] szProccessToKill;
break; <--- **If this is not a return 0;**
}
case 3:
{
break;
}
default:
break;
}
//Set Min / Max Width/Height size.
case WM_GETMINMAXINFO: <-- It will jump down here and give me an access violation error:
{
MINMAXINFO* MMI = (MINMAXINFO*)lparam;
MMI->ptMaxTrackSize.x = 375;
MMI->ptMaxTrackSize.y = 100;
MMI->ptMinTrackSize.x = 375;
MMI->ptMinTrackSize.y = 100;
return 0;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, message, wparam, lparam);
}
return 0;
}
I will kinda shorten it up straight to the problem for you guys:
SetWindowText(hUserBox, szDefault);
}
delete[] szProccessToKill;
break; <--- **If this is not a return 0;**
}
case 3:
{
break;
}
default:
break;
}
//Set Min / Max Width/Height size.
case WM_GETMINMAXINFO: <-- It will jump down here and give me an access violation error:
{
MINMAXINFO* MMI = (MINMAXINFO*)lparam;
MMI->ptMaxTrackSize.x = 375;
MMI->ptMaxTrackSize.y = 100;
MMI->ptMinTrackSize.x = 375;
MMI->ptMinTrackSize.y = 100;
return 0;
}
I'm having a problem in my program whenever I close the child window, the main window also exits.
I am a newbie in this programming.
The Correct Code:
/**
#file MainWindow.cpp
#author Andro Bondoc
#date 2011-02-11
*/
/** #file MainWindow.cpp #author Andro Bondoc #date 2011-02-11 */
#include "tray.h"
#define WM_USER_SHELLICON WM_USER + 1
HWND hWnd, Button, LoadNew, TextBox;
HINSTANCE hInst;
HICON hMainIcon;
HMENU hPopMenu;
NOTIFYICONDATA structNID;
long PASCAL WndProcParent(HWND,UINT,UINT,LONG);
long PASCAL WndProcChild(HWND,UINT,UINT,LONG);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
WNDCLASS wc, ws;
hInst = hInstance;
if(!hPrevInstance)
{
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProcParent;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance,(LPCTSTR)MAKEINTRESOURCE(IDI_TRAYICON));//LoadIcon(NULL,IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
wc.lpszMenuName = NULL;
wc.lpszClassName = "Data Retriever Parent";
RegisterClass(&wc);
ws.style = CS_HREDRAW | CS_VREDRAW;
ws.lpfnWndProc = WndProcChild;
ws.cbClsExtra = 0;
ws.cbWndExtra = 0;
ws.hInstance = hInstance;
ws.hIcon = LoadIcon(hInstance,(LPCTSTR)MAKEINTRESOURCE(IDI_TRAYICON));//LoadIcon(NULL,IDI_APPLICATION);
ws.hCursor = LoadCursor(NULL,IDC_ARROW);
ws.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
ws.lpszMenuName = NULL;
ws.lpszClassName = "Data Retriever Child";
RegisterClass(&ws);
}
hWnd = CreateWindowEx(0, wc.lpszClassName, "Data Retriever",
WS_BORDER | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
LoadNew = CreateWindowEx(0, ws.lpszClassName, "Help Program",
WS_BORDER | WS_CAPTION | WS_CHILD,
120,
80,
500,
300,
hWnd, NULL, hInstance, NULL);
hMainIcon = LoadIcon(hInstance,(LPCTSTR)MAKEINTRESOURCE(IDI_TRAYICON));
structNID.cbSize = sizeof(NOTIFYICONDATA);
structNID.hWnd = (HWND) hWnd;
structNID.uID = IDI_TRAYICON;
structNID.uFlags = NIF_ICON | NIF_MESSAGE;
structNID.hIcon = hMainIcon;
structNID.uCallbackMessage = WM_USER_SHELLICON;
Shell_NotifyIcon(NIM_ADD, &structNID);
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
long FAR PASCAL WndProcParent(HWND hwnd,UINT message,UINT wParam,long lParam)
{
HDC hdc = NULL;
POINT lpClickPoint;
char buff[100] = "";
switch(message){
case WM_CREATE:
Button = CreateWindowEx(WS_EX_WINDOWEDGE, "BUTTON", "Close",
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 680,480, 80, 30, hwnd, (HMENU)ID_CLOSE,
GetModuleHandle(NULL), NULL);
Button = CreateWindowEx(WS_EX_WINDOWEDGE, "BUTTON", "Help",
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 680,450, 80, 30, hwnd, (HMENU)ID_HELPDAW,
GetModuleHandle(NULL), NULL);
break;
/*case WM_DESTROY:
PostQuitMessage(0);
return 0;*/
case WM_USER_SHELLICON:
switch(LOWORD(lParam))
{
case WM_LBUTTONDBLCLK:
ShowWindow(hwnd, SW_RESTORE);
break;
case WM_RBUTTONDOWN:
//get mouse cursor position x and y as lParam has the message itself
GetCursorPos(&lpClickPoint);
//place the window/menu there if needed
hPopMenu = CreatePopupMenu();
InsertMenu(hPopMenu,0xFFFFFFFF,MF_BYPOSITION|MF_STRING,ID_OPEN,"&Open");
InsertMenu(hPopMenu,0xFFFFFFFF,MF_BYPOSITION|MF_STRING,ID_HELPDAW,"&Help");
InsertMenu(hPopMenu,0xFFFFFFFF,MF_BYPOSITION|MF_STRING,ID_CLOSE,"&Exit");
//workaround for microsoft bug, to hide menu w/o selecting
SetForegroundWindow(hWnd);
TrackPopupMenu(hPopMenu,TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_BOTTOMALIGN,lpClickPoint.x, lpClickPoint.y,0,hWnd,NULL);
SendMessage(hWnd,WM_NULL,0,0);
//MessageBox(NULL,"TEST rightclick","Testing ...",MB_OK);
return TRUE;
}
break;
case WM_COMMAND:
if(ID_CLOSE == LOWORD(wParam))
{
int iRes = MessageBox(NULL,"Do you want to Exit","Data Retriever",MB_YESNO|MB_ICONQUESTION);
if(IDYES == iRes)
{
Shell_NotifyIcon(NIM_DELETE,&structNID);
DestroyWindow(hWnd);
PostQuitMessage(0);
}
}
else if(ID_HELPDAW == LOWORD(wParam))
{
ShowWindow(LoadNew, SW_SHOW);
//MessageBox(NULL, "Help","Data Retriever",MB_OK|MB_ICONQUESTION);
}
else if(ID_OPEN == LOWORD(wParam))
{
ShowWindow(hWnd, SW_NORMAL);
}
break;
case WM_CLOSE:
Shell_NotifyIcon(NIM_DELETE,&structNID);
DestroyWindow(hWnd);
PostQuitMessage(0);
break;
case WM_SYSCOMMAND:
if(SC_MINIMIZE == wParam)
{
ShowWindow(hWnd,SW_HIDE);
return TRUE;
}
break;
}
return DefWindowProc(hwnd,message,wParam,lParam);
}
long FAR PASCAL WndProcChild(HWND hwnd,UINT message,UINT wParam,long lParam){
HDC hdc = NULL;
PAINTSTRUCT ps;
char buff[100] = "";
switch(message){
case WM_CREATE:
Button = CreateWindowEx(WS_EX_WINDOWEDGE, "BUTTON", "Unload",
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 20,20, 80, 30, hwnd, (HMENU)ID_MESSAGE,
GetModuleHandle(NULL), NULL);
break;
case WM_COMMAND:
if(ID_RETURN == LOWORD(wParam))
{
ShowWindow(hWnd, SW_SHOW);
ShowWindow(LoadNew,SW_HIDE);
//MessageBox(NULL, "Help","Data Retriever",MB_OK|MB_ICONQUESTION);
}
case WM_CLOSE:
ShowWindow(hWnd, SW_SHOW);
ShowWindow(LoadNew,SW_HIDE);
break;
case WM_PAINT:
RECT rect;
GetClientRect(LoadNew,&rect);
hdc = BeginPaint(LoadNew,&ps);
strcpy_s(buff,"TOP");
DrawText(hdc,buff,strlen(buff), &rect,DT_SINGLELINE|DT_CENTER|DT_TOP);
strcpy_s(buff,"RIGHT");
DrawText(hdc,buff,strlen(buff), &rect,DT_SINGLELINE|DT_VCENTER|DT_RIGHT);
strcpy_s(buff,"BOTTOM");
DrawText(hdc,buff,strlen(buff), &rect,DT_SINGLELINE|DT_CENTER|DT_BOTTOM);
strcpy_s(buff,"LEFT");
DrawText(hdc,buff,strlen(buff), &rect,DT_SINGLELINE|DT_VCENTER|DT_LEFT);
strcpy_s(buff,"CENTER");
DrawText(hdc,buff,strlen(buff), &rect,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
strcpy_s(buff,"BOTTOM-LEFT");
DrawText(hdc,buff,strlen(buff), &rect,DT_SINGLELINE|DT_BOTTOM|DT_LEFT);
strcpy_s(buff,"BOTTOM-RIGHT");
DrawText(hdc,buff,strlen(buff), &rect,DT_SINGLELINE|DT_BOTTOM|DT_RIGHT);
strcpy_s(buff,"TOP-LEFT");
DrawText(hdc,buff,strlen(buff), &rect,DT_SINGLELINE|DT_TOP|DT_LEFT);
strcpy_s(buff,"TOP-RIGHT");
DrawText(hdc,buff,strlen(buff), &rect,DT_SINGLELINE|DT_TOP|DT_RIGHT);
EndPaint(LoadNew,&ps);
break;
}
return DefWindowProc(hwnd,message,wParam,lParam);
}
You have the same wndproc code for each window. For WM_CLOSE, you DestroyWindow(hWnd), where hWnd is the global that stores your main window.
So, closing your child window closes the main window because you told it to.
Your modified code is still using the same WndProc for both windows. You tried to call RegisterClass twice with the same class name. The WndProcs will not be separated until you change the name.
ws.lpszClassName = "Data Retriever CHILD";
This problem would have been more readily apparent if you had checked the return value from RegisterClass - currently, the second call fails. There's other problems with this code (the MessageBox call in the child WndProc is really obnoxious, for example), but this change should be enough to get you headed in the right direction.