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.
Related
I want to disable the radio buttons when I select the checkbox. It works when I pass hwnd in addFunc2(), however, I need it to be in the second tab but somehow I can't find any way to make it work.
I apologize if its confusing, I'm very new at this, and my first time posting here. Please let me know if I need to clarify it more. Please refer to the images and some of my code below:
Result of code:
What I need:
HWND hRadio1, hRadio2, hTab, g_tabPanes[2];
HWND CreateTabPane(HWND tabctrl, int id, HINSTANCE instance)
{
RECT rcTab;
GetClientRect(tabctrl, &rcTab);
TabCtrl_AdjustRect(tabctrl, FALSE, &rcTab);
int wd = rcTab.right - rcTab.left;
int hgt = rcTab.bottom - rcTab.top;
return CreateWindow(
L"static", L"",
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
rcTab.left, rcTab.top, wd, hgt,
tabctrl,
(HMENU)id,
instance,
NULL
);
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE:
{
addControl(hwnd);
HINSTANCE hInst = GetModuleHandle(NULL);
RECT rc; int dx, dy;
GetClientRect(hwnd, &rc);
dx = rc.right - rc.left;
dy = rc.bottom - rc.top;
TCITEM tie = {
TCIF_TEXT | TCIF_IMAGE,
0, 0,
NULL,
0, -1, 0
};
hTab = CreateWindowEx(NULL, WC_TABCONTROL, _T(""),
WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS,
0, 0, dx, dy, hwnd,
(HMENU)1001, hInst, NULL
);
tie.pszText = (LPWSTR)_T("Tab 1");
TabCtrl_InsertItem(hTab, 0, &tie);
tie.pszText = (LPWSTR)_T("Tab 2");
TabCtrl_InsertItem(hTab, 1, &tie);
for (int i = 0; i < 2; i++)
g_tabPanes[i] = CreateTabPane(hTab, TAB_ID + i, hInst);
addFunc1(g_tabPanes[0]);
addFunc2(g_tabPanes[1]);
break;
}
case WM_COMMAND:
{
switch (wParam)
{
case ID_CHECKBOX:
{
switch (HIWORD(wParam))
{
case BN_CLICKED:
if (SendDlgItemMessage(hwnd, ID_CHECKBOX, BM_GETCHECK, 0, 0))
{
EnableWindow(hRadio1, true);
EnableWindow(hRadio2, true);
}
else
{
EnableWindow(hRadio1, false);
EnableWindow(hRadio2, false);
}
break;
}
}
break;
case WM_NOTIFY:
{
LPNMHDR ns = (LPNMHDR)lParam;
if ((ns->idFrom == 1001) && (ns->code == TCN_SELCHANGE))
{
int pane = TabCtrl_GetCurSel(hTab);
for (int i = 0; i < 2; i++)
if (pane == i)
ShowWindow(g_tabPanes[i], SW_SHOW);
else
ShowWindow(g_tabPanes[i], SW_HIDE);
}
}
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
void addFunc2(HWND hwnd)
{
HWND hCheckbox;
CreateWindow(TEXT("static"), TEXT("Duplex: "), WS_CHILD | WS_VISIBLE,
75, 10, 90, 25, hwnd, NULL, NULL, NULL);
hCheckbox = CreateWindow(L"button", L"Print on both sides", WS_CHILD | WS_VISIBLE |
BS_AUTOCHECKBOX | WS_TABSTOP,
75, 30, 150, 30, hwnd, (HMENU)ID_CHECKBOX, g_hinst, NULL);
hRadio1 = CreateWindow(L"button", L"Flip on long edge", WS_CHILD | WS_VISIBLE |
BS_AUTORADIOBUTTON | WS_TABSTOP,
75, 55, 150, 30, hwnd, (HMENU)ID_RADIO1, g_hinst, NULL);
hRadio2 = CreateWindow(L"button", L"Flip on short edge", WS_CHILD | WS_VISIBLE |
BS_AUTORADIOBUTTON | WS_TABSTOP,
75, 80, 150, 30, hwnd, (HMENU)ID_RADIO2, g_hinst, NULL);
SendMessage(hCheckbox, BM_SETCHECK, BST_CHECKED, 0);
SendMessage(hRadio1, BM_SETCHECK, BST_CHECKED, 0);
Currently only WM_MOUSEMOVE works. The image changes, but WM_MOUSELEAVE doesn't work anymore.
I want to make a hover effect on the button. What am I doing wrong?
[...]
hWndButton= CreateWindowW(L"Static", NULL, WS_CHILD | WS_VISIBLE | SS_BITMAP |
SS_NOTIFY, 10, 25, 109, 30, hwnd, (HMENU)4, NULL, NULL);
[...]
bool TheButtonToggle = false;
[...]
case WM_MOUSEMOVE:
if (TheButtonToggle == false) {
TRACKMOUSEEVENT tm_Event;
tm_Event.cbSize = sizeof(TRACKMOUSEEVENT);
tm_Event.dwFlags = TME_LEAVE;
tm_Event.hwndTrack = GetDlgItem((HWND)dwRefData, IDB_BUTTON);
TrackMouseEvent(&tm_Event);
TheButtonToggle = true;
HBITMAP hbmpButtonHover = LoadBitmap(hinst, MAKEINTRESOURCE(IDB_HOVER_BUTTON));
SendMessage(hWndButton, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbmpButtonHover);
}
break;
case WM_MOUSELEAVE:
{
HBITMAP hbmpButton = LoadBitmap(hinst, MAKEINTRESOURCE(IDB_BUTTON));
SendMessage(hWndButton, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbmpButton);
TheButtonToggle = false;
break;
}
A workaround:
You can subclass a button to monitor mouse move, if mouse move on the button, WM_MOUSEMOVE message in the subclass callback function will be triggered.
hWndButton = CreateWindowW(L"Static", NULL, WS_CHILD | WS_VISIBLE | SS_BITMAP |
SS_NOTIFY, 10, 25, 109, 30, hWnd, (HMENU)IDC_BUTTON, NULL, NULL);
SetWindowSubclass(hWndButton, &OwnerDrawButtonProc, IDC_BUTTON, 0);
[...]
LRESULT CALLBACK OwnerDrawButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
switch (uMsg)
{
case WM_MOUSEMOVE:
{
HBITMAP hbmpButton = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP3));
SendMessage(hWndButton, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbmpButton);
}
case WM_NCDESTROY:
RemoveWindowSubclass(hWnd, &OwnerDrawButtonProc, 1);
break;
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
Debug:
I give the background main window color by registering the window class with the hbrBackground property like this :
wcex.hbrBackground = (HBRUSH)GetStockObject(DKGRAY_BRUSH);
and then :
RegisterClassExW(&wcex);
The result window is white. I have the darkgray color when I minimize/maximize the window.
How can I obtain the darkgray background immediately ?
Thank you !
EDIT : The callback function :
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND hgGroupBox1;
static HWND hsFileSize;
static HWND hsFileName;
static HWND hsStatic1;
static HWND hsStatic2;
static HWND hsStatic3;
static HWND hsStatic4;
static HWND hsFileID;
static HWND hlbTagV2Frames;
static HWND hStatus;
static HBRUSH hbrBkgnd;
int hauteur, largeur;
std::wstringstream lbFrames;
switch (message)
{
case WM_CREATE:
hsStatic1 = CreateWindowEx(0, L"STATIC", L"Fichier :", WS_CHILD | WS_VISIBLE, 5, 5, 60, 20, hWnd, (HMENU)ID_STATIC1, (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE), nullptr);
hsFileName = CreateWindowEx(0, L"STATIC", L"", WS_CHILD | WS_VISIBLE, 65, 5, 800, 20, hWnd, (HMENU)ID_STATICFILENAME, (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE), nullptr);
hgGroupBox1 = CreateWindowEx(0, L"BUTTON", L"TagV2", WS_CHILD | WS_VISIBLE | BS_GROUPBOX, 5, 30, 420, hauteur - 100, hWnd, (HMENU)ID_GROUPEBOX1, (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE), nullptr);
hsStatic2 = CreateWindowEx(0, L"STATIC", L"Taille :", WS_CHILD | WS_VISIBLE, 15, 50, 100, 20, hWnd, (HMENU)ID_STATIC2, (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE), nullptr);
hsFileSize = CreateWindowEx(0, L"STATIC", nullptr, WS_CHILD | WS_VISIBLE | WS_BORDER, 15, 75, 100, 20, hWnd, (HMENU) ID_STATICFILESIZE, (HINSTANCE) GetWindowLongPtr(hWnd, GWLP_HINSTANCE), nullptr);
hsStatic3 = CreateWindowEx(0, L"STATIC", L"Entête :", WS_CHILD | WS_VISIBLE, 15, 100, 100, 20, hWnd, (HMENU)ID_STATIC3, (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE), nullptr);
hsFileID = CreateWindowEx(0, L"STATIC", nullptr, WS_CHILD | WS_VISIBLE | WS_BORDER, 15, 125, 200, 20, hWnd, (HMENU)ID_STATICENTETEID, (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE), nullptr);
hsStatic4 = CreateWindowEx(0, L"STATIC", L"Attributs du tagV2 :", WS_CHILD | WS_VISIBLE, 15, 150, 150, 20, hWnd, (HMENU)ID_GROUPEBOX1, (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE), nullptr);
hlbTagV2Frames = CreateWindow(L"LISTBOX", L"", WS_VISIBLE | WS_CHILD | WS_BORDER | LBS_NOTIFY, 15, 175, 400, 200, hWnd, (HMENU)ID_LISTBOXFRAMES, (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE), nullptr);
ShowWindow(hsStatic1, SW_SHOW);
ShowWindow(hgGroupBox1, SW_SHOW);
ShowWindow(hsStatic2, SW_SHOW);
ShowWindow(hsFileSize, SW_SHOW);
ShowWindow(hsStatic3, SW_SHOW);
ShowWindow(hsFileID, SW_SHOW);
ShowWindow(hStatus, SW_SHOW);
ShowWindow(hsStatic4, SW_SHOW);
ShowWindow(hlbTagV2Frames, SW_SHOW);
break;
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Analyse les sélections de menu :
switch (wmId)
{
case IDM_FICHIER_OUVRIR:
//Here comes the file treatement code.
}
break;
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: Ajoutez ici le code de dessin qui utilise hdc...
EndPaint(hWnd, &ps);
}
break;
case WM_CTLCOLORSTATIC:
{
HDC hdcStatic = (HDC)wParam;
SetTextColor(hdcStatic, RGB(0, 0, 0));
SetBkColor(hdcStatic, DKGRAY_BRUSH);
hbrBkgnd = CreateSolidBrush(DKGRAY_BRUSH);
return (INT_PTR)hbrBkgnd;
}
}
case WM_CTLCOLORBTN:
{
HDC hdcButton = (HDC)wParam;
SetTextColor(hdcButton, RGB(255, 255, 255));
SetBkColor(hdcButton, DKGRAY_BRUSH);
}
hbrBkgnd = CreateSolidBrush(DKGRAY_BRUSH);
return (INT_PTR)hbrBkgnd;
case WM_ERASEBKGND:
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
WM_ERASEBKGND : Sent when the window background must be erased (for example, when a window is resized). The message is sent to
prepare an invalidated portion of a window for painting.
The simplest solution: delete WM_ERASEBKGND message or add return DefWindowProc(hWnd, message, wParam, lParam) in the WM_ERASEBKGND message if you do not want delete WM_ERASEBKGND.
You could use WM_PAINT to fill the main window with the Brush using FillRect in your windows procedure. That should accomplish what you want.
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, reinterpret_cast<HBRUSH>(COLOR_ACTIVECAPTION + 1));
EndPaint(hwnd, &ps);
} return 0;
See the FillRect function https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-fillrect
Having simple window, button which opens dialog. But I want to add close button to it.
I have tried to add close button with adding WM_SYSMENU, with adding EnableMenuItem, but it didn't work:
Minimal code is:
resource.rc:
IDD_FORMVIEW DIALOGEX 0, 0, 178, 86
STYLE DS_SETFONT | DS_CONTROL | WS_VISIBLE | WS_SYSMENU
EXSTYLE WS_EX_OVERLAPPEDWINDOW
CAPTION "TEST"
FONT 12, "Microsoft Sans Serif", 400, 0, 0xCC
BEGIN
CTEXT "Test",IDC_STATIC,46,4,74,8,0,WS_EX_CLIENTEDGE
END
resource.h:
#define IDD_FORMVIEW 101
Test.cpp:
hwndButton = CreateWindowW(L"BUTTON",
L"ENTER",
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_CLIPSIBLINGS,
605, 510, 255, 45,
hWnd, (HMENU)1, NULL, NULL);
case WM_COMMAND:
{
switch (LOWORD(wParam)) {
case 2: {
if (hwndHTDW == NULL) {
hwndHTDW = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_FORMVIEW), hWnd, DialogProc);
ShowWindow(hwndHTDW, SW_SHOW);
UpdateWindow(hwndHTDW);
}
}
break;
}
}
{
switch (msg) {
case WM_INITDIALOG: {
EnableMenuItem(GetSystemMenu(hwnd, FALSE), SC_CLOSE,
MF_BYCOMMAND | MF_ENABLED);
return TRUE;
}
break;
default:
return FALSE;
}
return TRUE;
Modify your code a little bit.
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
hwndButton = CreateWindowW(L"BUTTON",
L"ENTER",
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_CLIPSIBLINGS,
605, 510, 255, 45,
hWnd, (HMENU)1, NULL, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
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;
case 1:
{
if (hwndHTDW == NULL)
{
hwndHTDW = CreateDialog(hInst, MAKEINTRESOURCE(IDD_FORMVIEW), hWnd, DialogProc);
Button_Close = CreateWindowW(L"BUTTON",
L"CLOSE",
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_CLIPSIBLINGS | WS_TABSTOP,
130, 100, 80, 30,
hwndHTDW, (HMENU)2, NULL, NULL);
ShowWindow(hwndHTDW, SW_SHOW);
UpdateWindow(hwndHTDW);
}
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code that uses hdc here...
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
BOOL CALLBACK DialogProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
BOOL fError;
switch (message)
{
case WM_INITDIALOG:
{
EnableMenuItem(GetSystemMenu(hwnd, FALSE), SC_CLOSE,
MF_BYCOMMAND | MF_ENABLED);
return TRUE;
}
break;
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case 2:
{
EndDialog(hwnd, LOWORD(wParam));
return (INT_PTR)TRUE;
}
default:
break;
}
}
default:
return FALSE;
}
return TRUE;
}
Updated:
Create an extra button through CreateWindow and pass the handle of the dialog box to the button as a parameter.
HWND Button_Close = CreateWindowW(L"BUTTON",
L"CLOSE",
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_CLIPSIBLINGS | WS_TABSTOP,
130, 100, 80, 30,
hwndHTDW, (HMENU)2, NULL, NULL);
In the callback function of the dialog box, add the WM_COMMAND event and add the following code.
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case 2:
{
EndDialog(hwnd, LOWORD(wParam));
return (INT_PTR)TRUE;
}
}
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.