I am coding my first program with GUI using only pure WinAPI. But I faced some strange problem.
There are 2 ListView elements on the form to output some values. When scrollbar appears on second ListView, all child objects on the form disappears. And scrollbar of that ListView is flickering. And when I push on that ListView all get back to normal. I don't know what to do.
But this problem applies only to the second ListView element, hListViewCh on the form. There is all ok with the first element.
Here is the code:
case WM_CREATE:
{
GetClientRect(hWnd, &Rect);
h_Chk1 = CreateWindow(TEXT("button"), TEXT("Graphic"),
WS_VISIBLE | WS_CHILD | BS_CHECKBOX,
Rect.right - 550,
300 + 10,
100,
20,
hWnd, (HMENU)0xCB01, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL);
h_Chk2 = CreateWindow(TEXT("button"), TEXT("Diagram"),
WS_VISIBLE | WS_CHILD | BS_CHECKBOX,
Rect.right - 550,
300 + 35,
100,
20,
hWnd, (HMENU)0xCB02, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL);
CheckDlgButton(hWnd, 0xCB01, BST_UNCHECKED);
CheckDlgButton(hWnd, 0xCB02, BST_UNCHECKED);
hListViewCh = CreateWindow(
WC_LISTVIEW,
_T("MyList"),
LVS_REPORT|WS_CHILD|WS_VISIBLE,
Rect.right - 265,
377,
250,
200,
hWnd, (HMENU)listViewCh, (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), NULL);
//--
LVCOLUMN lvColumn = {0};
lvColumn.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT;
lvColumn.fmt = LVCFMT_CENTER;
lvColumn.pszText = "№";
lvColumn.cx = 30;
ListView_InsertColumn(hListViewCh, 0, &lvColumn);
lvColumn.pszText = "Property";
lvColumn.cx = 70;
ListView_InsertColumn(hListViewCh, 1, &lvColumn);
lvColumn.pszText = "Value";
lvColumn.cx = 120;
ListView_InsertColumn(hListViewCh, 2, &lvColumn);
//--
hListView = CreateWindow(
WC_LISTVIEW,
_T("Set of variate values"),
LVS_REPORT|WS_CHILD|WS_VISIBLE,
Rect.right - 550,
Rect.top + 15,
535,
275,
hWnd,
(HMENU)listView,
(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
NULL);
//--
lvColumn.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT;
lvColumn.pszText = "No";
lvColumn.fmt = LVCFMT_CENTER;
lvColumn.cx = 43;
ListView_InsertColumn(hListView, 0, &lvColumn);
//--
lvColumn.pszText = "[ a[i-1] , a[i] )";
lvColumn.cx = 151;
ListView_InsertColumn(hListView, 1, &lvColumn);
//--
lvColumn.pszText = "xi";
lvColumn.cx = 85;
ListView_InsertColumn(hListView, 2, &lvColumn);
//--
lvColumn.pszText = "ni";
ListView_InsertColumn(hListView, 3, &lvColumn);
//--
lvColumn.pszText = "V";
ListView_InsertColumn(hListView, 4, &lvColumn);
//--
lvColumn.pszText = "EV";
ListView_InsertColumn(hListView, 5, &lvColumn);
break;
}
There is some redraw functions in WM_PAINT to make ListViews move with a window on maximizing.
//-- LISTVIEW POSITION
SetWindowPos(hListViewCh, NULL,\
Rect.right - 265,
312,
250,
200,
SWP_NOSIZE);
//-- LISTVIEW POSITION
SetWindowPos(hListView, NULL,\
Rect.right - 550,\
Rect.top + 15,\
535,\
340,\
SWP_NOSIZE|SWP_NOZORDER);
//--
Resizing child windows in a WM_PAINT is simply wrong and I suspect this to be a big part of your problems.
The code to position the child windows should be run in response to the WM_WINDOWPOSCHANGED message.
Related
How can I add some elements(window) in my tab?
Use these:
INITCOMMONCONTROLSEX icex;
TCITEMW tie;
WM_CREATE:
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC = ICC_TAB_CLASSES;
InitCommonControlsEx(&icex);
Tab = CreateWindowW(WC_TABCONTROLW, NULL, WS_CHILD | WS_VISIBLE,
0, 0, 200, 150, hwnd, (HMENU)ID_TABCTRL, NULL, NULL);
CreateWindowW(WC_BUTTONW, L"Add", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
250, 50, 100, 25, hwnd, (HMENU)BTN_ADD, NULL, NULL);
In BTN_ADD I make two tabs.
case BTN_ADD: {
tie.mask = TCIF_TEXT;
tie.pszText = (LPWSTR)L"TAB1";
SendMessageW(Tab, TCM_GETITEMCOUNT, 0, 0);
SendMessageW(Tab, TCM_INSERTITEMW, 1, (LPARAM)(LPTCITEM)&tie);
tie.mask = TCIF_TEXT;
tie.pszText = (LPWSTR)L"TAB2";
SendMessageW(Tab, TCM_GETITEMCOUNT, 0, 0);
SendMessageW(Tab, TCM_INSERTITEMW, 2, (LPARAM)(LPTCITEM)&tie);
SendMessageW(Tab, TCM_GETITEMCOUNT, 0, 0);
//Add item in tab
CreateWindowW(WC_BUTTONW, L"BTN", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
50, 50, 30, 30, Tab, NULL, NULL, NULL);
break;
}
But this button added in hwnd (main), and when I open other tab, I continue to see this button. I need add content in a certain tab.
First tab
Second tab
I solved a problem. Understand, that need use a MoveWindow function. These tabs isn't content, but content attachment to window (Tab). I just created Tab via:
Tab = CreateWindowW(WC_TABCONTROLW, NULL, WS_CHILD | WS_VISIBLE,
0, 0, TAB_WEIGHT, TAB_HEIGHT,
hwnd, (HMENU)ID_TABCTRL, NULL, NULL);
Then I put down a few window (ListBox) on the Tab (which window).
ListBoxProcesses = CreateWindowEx(WS_EX_CLIENTEDGE, L"ListBox", NULL,
WS_CHILD | WS_VISIBLE | LBS_STANDARD | LBS_WANTKEYBOARDINPUT,
0, 50, TAB_WEIGHT - 20, TAB_HEIGHT - 100,
Tab, (HMENU)ID_LIST, NULL, NULL);
ListBoxModules = CreateWindowEx(WS_EX_CLIENTEDGE, L"ListBox", NULL,
WS_CHILD | WS_VISIBLE | LBS_STANDARD | LBS_WANTKEYBOARDINPUT,
TAB_WEIGHT, 50, TAB_WEIGHT - 20, TAB_HEIGHT - 100,
Tab, (HMENU)ID_LIST, NULL, NULL);
But there is one feature. First window (ListBoxProcesses) has a horizontal position 0. But second window (ListBoxModules) has TAB_WEIGHT. After I choose other tab, I call a MoveWindow function and its shifts my content.
Btw, yes, I understand that need use WM_NOTIFY message which contains this:
switch (wParam)
{
case ID_TABCTRL: {
switch (SendMessageW(Tab, TCM_GETCURFOCUS, 0, 0))
{
case FIRST_PAGE: {
MoveWindow(ListBoxProcesses, 0, 50, TAB_WEIGHT - 20, TAB_HEIGHT - 100, TRUE);
MoveWindow(ListBoxModules, TAB_WEIGHT, 50, TAB_WEIGHT - 20, TAB_HEIGHT - 100, TRUE);
break;
}
case SECOND_PAGE: {
MoveWindow(ListBoxProcesses, -TAB_WEIGHT, 50, TAB_WEIGHT - 20, TAB_HEIGHT - 100, TRUE);
MoveWindow(ListBoxModules, 0, 50, TAB_WEIGHT - 20, TAB_HEIGHT - 100, TRUE);
break;
}
default:
break;
}
break;
}
default:
break;
}
First tab
Second tab
I've been fiddling around with custom windows using the windows API. As of such I have been working with Extended Layered Windows. I have the window drawn, and it works. However when resizing the window there is an odd flickering/glitching [(Screenshot) ][1]when the redraw/UpdateLayeredWindow (and UpdateLayeredWindowIndirect) method is called. Is there anything I'm doing wrong here?
void redrawBaseWindow(HWND window) {
RECT rect;
GetWindowRect(window, &rect);
int elipseDiam = ((rect.right - rect.left)+(rect.bottom-rect.top))/2*0.025;
HDC mainDC = GetDC(NULL);
POINT destination = { rect.left,rect.top };
POINT zero = destination;
SIZE size = { rect.right - rect.left,rect.bottom - rect.top };
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.AlphaFormat = 0;
bf.SourceConstantAlpha = 255;
HBRUSH brush = CreateSolidBrush(RGB(255, 0, 100));
HBRUSH oldbrush = SelectObject(mainDC, brush);
HPEN pen = CreatePen(PS_NULL, 0, RGB(0, 0, 0));
HPEN oldPen = SelectObject(mainDC, pen);
HBITMAP bmp = CreateCompatibleBitmap(mainDC, size.cx,size.cy);
HBITMAP oldBmp = SelectObject(mainDC, bmp);
FillRect(mainDC, &rect, CreateSolidBrush(RGB(0, 0, 0)));
Rectangle(mainDC, rect.left, rect.top + elipseDiam/2, rect.right, rect.bottom - elipseDiam/2);
Rectangle(mainDC, rect.left + elipseDiam/2, rect.top, rect.right - elipseDiam/2, rect.bottom);
UPDATELAYEREDWINDOWINFO updated = { sizeof(UPDATELAYEREDWINDOWINFO), NULL, &destination, &size, mainDC, &zero, RGB(0,0,0),&bf, ULW_COLORKEY, &rect};
UpdateLayeredWindowIndirect(window, &updated);
//BOOL error = UpdateLayeredWindow(window, NULL, &destination, &size, mainDC, &zero, RGB(0, 0, 0), &bf, ULW_COLORKEY);
SelectObject(mainDC, oldbrush);
SelectObject(mainDC, oldBmp);
SelectObject(mainDC, oldPen);
DeleteObject(brush);
DeleteObject(bmp);
DeleteObject(pen);
}
Just in case, the Window Message Proc.
long __stdcall WndProc(HWND window, unsigned int msg, WPARAM wp, LPARAM lp) {
PAINTSTRUCT ps;
HDC hdc;
TCHAR greeting[] = "Hello, World!";
RECT rect_window;
GetWindowRect(window, &rect_window);
switch (msg) {
case WM_SYSKEYDOWN:
MessageBeep(MB_ICONERROR);
case WM_CREATE:
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_NCHITTEST:;
int x = LOWORD(lp);
int y = HIWORD(lp);
if (x > rect_window.left && x<rect_window.right && y>rect_window.top && y < rect_window.top + 25)
return HTCAPTION;
if (x>=rect_window.left-3 && x<=rect_window.left+3)
return HTLEFT;
if (x >= rect_window.right - 3 && x <= rect_window.right + 3)
return HTRIGHT;
if (y >= rect_window.top - 3 && y <= rect_window.top + 3)
return HTTOP;
if (y >= rect_window.bottom - 3 && y <= rect_window.bottom + 3)
return HTBOTTOM;
break;
case WM_LBUTTONDOWN:
break;
case WM_SIZE:
redrawBaseWindow(window);
break;
case WM_PAINT:
break;
}
return DefWindowProc(window, msg, wp, lp);
}
Edit:
Gif of the glitch
Edit 2:
Using CreateCompatibleDC value into UpdateLayeredWindow [Also not working]
void redrawBaseWindow(HWND window) {
RECT rect;
GetWindowRect(window, &rect);
int elipseDiam = ((rect.right - rect.left)+(rect.bottom-rect.top))/2*0.025;
HDC mainDC = GetDC(NULL);
HDC memDC = CreateCompatibleDC(mainDC);
POINT destination = { rect.left,rect.top };
POINT zero = destination;
SIZE size = { rect.right - rect.left,rect.bottom - rect.top };
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.AlphaFormat = 0;
bf.SourceConstantAlpha = 255;
HBRUSH brush = CreateSolidBrush(RGB(255, 0, 100));
HBRUSH oldbrush = SelectObject(memDC, brush);
HPEN pen = CreatePen(PS_NULL, 0, RGB(0, 0, 0));
HPEN oldPen = SelectObject(memDC, pen);
HBITMAP bmp = CreateCompatibleBitmap(memDC, size.cx,size.cy);
HBITMAP oldBmp = SelectObject(memDC, bmp);
FillRect(memDC, &rect, CreateSolidBrush(RGB(0, 0, 0)));
Rectangle(memDC, rect.left, rect.top + elipseDiam/2, rect.right, rect.bottom - elipseDiam/2);
Rectangle(memDC, rect.left + elipseDiam/2, rect.top, rect.right - elipseDiam/2, rect.bottom);
Ellipse(memDC, rect.left + elipseDiam, rect.top + elipseDiam, rect.left, rect.top); //Top-Left
Ellipse(memDC, rect.right - elipseDiam, rect.top, rect.right, rect.top + elipseDiam); //Top-Right
Ellipse(memDC, rect.left, rect.bottom, rect.left + elipseDiam, rect.bottom - elipseDiam); //Bottom-Left
Ellipse(memDC, rect.right - elipseDiam, rect.bottom, rect.right, rect.bottom - elipseDiam); //Bottom-Right
UPDATELAYEREDWINDOWINFO updated = { sizeof(UPDATELAYEREDWINDOWINFO), NULL, &destination, &size, memDC, &zero, RGB(0,0,0),&bf, ULW_COLORKEY, &rect};
UpdateLayeredWindowIndirect(window, &updated);
//BOOL error = UpdateLayeredWindow(window, NULL, &destination, &size, mainDC, &zero, RGB(0, 0, 0), &bf, ULW_COLORKEY);
SelectObject(memDC, oldbrush);
SelectObject(memDC, oldBmp);
SelectObject(memDC, oldPen);
DeleteObject(brush);
DeleteObject(bmp);
DeleteObject(pen);
ReleaseDC(NULL,mainDC);
ReleaseDC(NULL,memDC);
}
Edit 3: DeleteDC on CreateCompatibleDC device, as well as creation of bitmap on screen DC rather than CompatibleDC
void redrawBaseWindow(HWND window) {
RECT rect;
GetWindowRect(window, &rect);
int elipseDiam = ((rect.right - rect.left)+(rect.bottom-rect.top))/2*0.025;
HDC mainDC = GetDC(NULL);
HDC memDC = CreateCompatibleDC(mainDC);
POINT destination = { rect.left,rect.top };
POINT zero = destination;
SIZE size = { rect.right - rect.left,rect.bottom - rect.top };
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.AlphaFormat = 0;
bf.SourceConstantAlpha = 255;
HBRUSH brush = CreateSolidBrush(RGB(255, 0, 100));
HBRUSH oldbrush = SelectObject(memDC, brush);
HPEN pen = CreatePen(PS_NULL, 0, RGB(0, 0, 0));
HPEN oldPen = SelectObject(memDC, pen);
HBITMAP bmp = CreateCompatibleBitmap(mainDC, size.cx,size.cy);
HBITMAP oldBmp = SelectObject(memDC, bmp);
FillRect(memDC, &rect, CreateSolidBrush(RGB(0, 0, 0)));
Rectangle(memDC, rect.left, rect.top + elipseDiam/2, rect.right, rect.bottom - elipseDiam/2);
Rectangle(memDC, rect.left + elipseDiam/2, rect.top, rect.right - elipseDiam/2, rect.bottom);
Ellipse(memDC, rect.left + elipseDiam, rect.top + elipseDiam, rect.left, rect.top); //Top-Left
Ellipse(memDC, rect.right - elipseDiam, rect.top, rect.right, rect.top + elipseDiam); //Top-Right
Ellipse(memDC, rect.left, rect.bottom, rect.left + elipseDiam, rect.bottom - elipseDiam); //Bottom-Left
Ellipse(memDC, rect.right - elipseDiam, rect.bottom, rect.right, rect.bottom - elipseDiam); //Bottom-Right
UPDATELAYEREDWINDOWINFO updated = { sizeof(UPDATELAYEREDWINDOWINFO), NULL, &destination, &size, memDC, &zero, RGB(0,0,0),&bf, ULW_COLORKEY, &rect};
UpdateLayeredWindowIndirect(window, &updated);
//BOOL error = UpdateLayeredWindow(window, NULL, &destination, &size, mainDC, &zero, RGB(0, 0, 0), &bf, ULW_COLORKEY);
SelectObject(memDC, oldbrush);
SelectObject(memDC, oldBmp);
SelectObject(memDC, oldPen);
DeleteObject(brush);
DeleteObject(bmp);
DeleteObject(pen);
DeleteDC(memDC);
ReleaseDC(NULL,mainDC);
}
Original flickering fixed. Thanks [Jonathan Pottar]
Another error has occurred however : This
void redrawBaseWindow(HWND window) {
RECT rect;
GetWindowRect(window, &rect);
int elipseDiam = ((rect.right - rect.left)+(rect.bottom-rect.top))/2*0.025;
HDC mainDC = GetDC(NULL);
HDC memDC = CreateCompatibleDC(mainDC);
POINT destination = { rect.left,rect.top };
POINT zero = destination;
SIZE size = { rect.right - rect.left,rect.bottom - rect.top };
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.AlphaFormat = 0;
bf.SourceConstantAlpha = 255;
HBRUSH brush = CreateSolidBrush(RGB(255, 0, 100));
HBRUSH oldbrush = SelectObject(memDC, brush);
HPEN pen = CreatePen(PS_NULL, 0, RGB(0, 0, 0));
HPEN oldPen = SelectObject(memDC, pen);
HBITMAP bmp = CreateCompatibleBitmap(mainDC, size.cx,size.cy);
HBITMAP oldBmp = SelectObject(memDC, bmp);
FillRect(memDC, &rect, CreateSolidBrush(RGB(0, 0, 0)));
Rectangle(memDC, rect.left, rect.top + elipseDiam/2, rect.right, rect.bottom - elipseDiam/2);
Rectangle(memDC, rect.left + elipseDiam/2, rect.top, rect.right - elipseDiam/2, rect.bottom);
Ellipse(memDC, rect.left + elipseDiam, rect.top + elipseDiam, rect.left, rect.top); //Top-Left
Ellipse(memDC, rect.right - elipseDiam, rect.top, rect.right, rect.top + elipseDiam); //Top-Right
Ellipse(memDC, rect.left, rect.bottom, rect.left + elipseDiam, rect.bottom - elipseDiam); //Bottom-Left
Ellipse(memDC, rect.right - elipseDiam, rect.bottom, rect.right, rect.bottom - elipseDiam); //Bottom-Right
UPDATELAYEREDWINDOWINFO updated = { sizeof(UPDATELAYEREDWINDOWINFO), NULL, &destination, &size, memDC, &zero, RGB(0,0,0),&bf, ULW_COLORKEY, &rect};
UpdateLayeredWindowIndirect(window, &updated);
//BOOL error = UpdateLayeredWindow(window, NULL, &destination, &size, mainDC, &zero, RGB(0, 0, 0), &bf, ULW_COLORKEY);
SelectObject(memDC, oldbrush);
SelectObject(memDC, oldBmp);
SelectObject(memDC, oldPen);
DeleteObject(brush);
DeleteObject(bmp);
DeleteObject(pen);
DeleteDC(memDC);
ReleaseDC(NULL,mainDC);
}
This thankfully fixed my issue.
I have a window with two scrollbars, the scrollbars are repositioned when the window is resized. Inside the WM_PAINT handler, I draw a filled white rectangle just before the scrollbars:
Now, what I assumed will happen when I resize the window is the following:
First, a WM_SIZE message is sent. Inside its handler I reposition the
scrollbars.
Second, a WM_PAINT message is sent. Inside its handler I redraw
the filled white rectangle.
But when I resize the window vertically, this is what happens:
And when I resize the window horizontally, this is what happens:
This is my code:
#include <Windows.h>
HWND hHorizontalScrollbar;
HWND hVerticalScrollbar;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// Get width and height of client area for hWnd
RECT rect;
GetClientRect(hWnd, &rect);
// Draw a filled white rectangle just before the scrollbars
Rectangle(hdc, rect.left, rect.top, rect.right - 17, rect.bottom - 17);
EndPaint(hWnd, &ps);
}
break;
case WM_SIZE:
{
// Get width and height of client area for hWnd
RECT rect;
GetClientRect(hWnd, &rect);
// Change y and width of horizontal scrollbar
MoveWindow(hHorizontalScrollbar, 0, rect.bottom - 17, rect.right - 220, 17, TRUE);
// Change x and height of vertical scrollbar
MoveWindow(hVerticalScrollbar, rect.right - 17, 0, 17, rect.bottom - 220, TRUE);
}
break;
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = "WinClass";
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&wc);
HWND hWnd = CreateWindowEx(0, "WinClass", "", WS_OVERLAPPEDWINDOW, 600, 300, 400, 400, NULL, NULL, hInstance, NULL);
// Create horizontal Scrollbar
hHorizontalScrollbar = CreateWindowEx(0, "SCROLLBAR", NULL, WS_CHILD | WS_VISIBLE| SBS_HORZ, 0, 333, 300, 17, hWnd, NULL, hInstance, NULL);
// Create vertical Scrollbar
hVerticalScrollbar = CreateWindowEx(0, "SCROLLBAR", NULL, WS_CHILD | WS_VISIBLE| SBS_VERT, 333, 0, 17, 300, hWnd, NULL, hInstance, NULL);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
You can add InvalidateRect to repaint in WM_SIZE:
case WM_SIZE:
RECT rect;
GetClientRect(hWnd, &rect);
MoveWindow(hHorizontalScrollbar, 0, rect.bottom - 17, rect.right - 220, 17, TRUE);
MoveWindow(hVerticalScrollbar, rect.right - 17, 0, 17, rect.bottom - 220, TRUE);
InvalidateRect(hWnd, 0, TRUE); //*** add this
Also, to add scroller, you may not need to create controls, you can just add WS_VSCROLL and WS_HSCROLL flag:
HWND hWnd = CreateWindowEx(0, "WinClass", "", WS_VSCROLL|WS_HSCROLL|WS_OVERLAPPEDWINDOW, 600, 300, 400, 400, NULL, NULL, hInstance, NULL);
Note, if there is a lot of painting done in WM_PAINT then consider overriding WM_ERASEBKGND and break so it doesn't do anything. Do all the background painting in WM_PAINT. You still need InvalidateRect in WM_SIZE
Edit ---------------------------------
When you resize the window, WM_ERASEBKGND is called to update the background. WM_PAINT is called next, however not all WM_PAINT changes are shown on the screen. Windows thinks that there is only a thin line next to the control's edge which needs updating so only that area of the screen is repainted.
As noted by #xMRI, you should set wc.style = CS_HREDRAW | CS_VREDRAW. This would be same as calling InvalidateRect(hWnd, 0, FALSE) in WM_SIZE.
Sometimes you need InvalidateRect(hWnd, 0, TRUE) to force erasing all of the background, but the above example doesn't need full background erase. You can also try WS_CLIPCHILDREN flag to reduce flicker and strange repaint.
This question is follow up Win32 (GDI) - Set Opacity of STATIC Control
My problem is that my alpha blending function is not working and I was wondering if someone help me out?
Here is the Setup WndProc:
case WM_PAINT:
OnChildPaint(BeginPaint(hWnd, &ps));
EndPaint(hWnd, &ps);
break;
My OnChildPaint function:
BOOL
OnChildPaint(HDC i_hDC)
{
HDC hMemDC;
HGDIOBJ hOldObj;
HBITMAP hBitmap;
BLENDFUNCTION blendFunc_s = {AC_SRC_OVER, 0, 128, AC_SRC_ALPHA};
hMemDC = CreateCompatibleDC(i_hDC);
hBitmap = CreateCompatibleBitmap(hMemDC, 100, 100);
/* hBrush = CreateSolidBrush(RGB(255, 0, 0)); */
hOldObj = SelectObject(hMemDC, hBitmap);
BitBlt(i_hDC, 10, 100, 100, 100, hMemDC, 0, 0, SRCCOPY);
AlphaBlend(i_hDC, 10, 100, 100, 100, hMemDC, 10, 100, 100, 100, blendFunc_s);
SelectObject(hMemDC, hOldObj);
DeleteObject(hMemDC);
return TRUE;
}
Have that in mind that I'm not working with actual Bitmap Image (There is no Image).
Thanks
I'm using C - (NO MFC or GDI+) :-)
What I want is to set the opacity of my child window to let say 100 (my child window is a STATIC control). I was wondering if this is even possible and if so can someone please point me to the right direction on how to do it.
Here is my setup:
I create my Parent window as follow:
HWND hWnd;
WNDCLASS wndCls_s;
wndCls_s.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wndCls_s.lpfnWndProc = MainWndProc;
wndCls_s.cbClsExtra = 0;
wndCls_s.cbWndExtra = 0;
wndCls_s.hInstance = hInstance;
wndCls_s.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_BSN_64));
wndCls_s.hCursor = LoadCursor(NULL, IDC_ARROW);
wndCls_s.hbrBackground = CreateSolidBrush(RGB(0, 0, 0));
wndCls_s.lpszMenuName = NULL;
wndCls_s.lpszClassName = pszCName;
if (RegisterClass(&wndCls_s) == 0)
return EXIT_FAILURE;
/* Creating Window */
hWnd = CreateWindow(
pszCName, pszCName,
WS_VISIBLE | WS_POPUP | WS_SYSMENU | WS_CLIPCHILDREN,
0, 0, WND_WIDTH, WND_HEIGHT,
NULL, NULL, hInstance, NULL);
In my MainWndProc:
case WM_CREATE:
{
HWND hWndChild = CreateWindow(
L"STATIC", (LPCTSTR) NULL,
WS_CHILD | WS_VISIBLE,
10, 10, 110, 110,
hWnd, (HMENU) (int) 10000,
g_hInst, NULL);
}
break;
case WM_CTLCOLORSTATIC:
{
COLORREF dwColor;
dwColor = RGB(255, 0, 0);
hDC = (HDC) wParam;
//SetBkColor(hDC, dwColor);
SetBkMode(hDC, TRANSPARENT);
/*
This is not going to work for child window
SetWindowLong(
hWnd, GWL_EXSTYLE,
GetWindowLong((HWND)lParam, GWL_EXSTYLE) & ~WS_EX_LAYERED);
SetLayeredWindowAttributes(
(HWND)lParam, 0, 100, LWA_ALPHA);
RedrawWindow((HWND)lParam, NULL, NULL, RDW_ERASE | RDW_INVALIDATE);
*/
if (g_hBrushRed == NULL)
g_hBrushRed = CreateSolidBrush(dwColor);
}
return (INT_PTR)g_hBrushRed;
Why do you enable transparency with TRANSPARENT if you are going to return a valid brush for the background? You don't need SetBkMode and your red brush will be used by the control then.