I'm trying to give a color for 1 single HWND in my win32 api..
So far I managed to give color for txt/background but that's for all the static HWNDs I have as follows:
HWND txtview1
HWND txtview2
HDC hdcStatic = (HDC)wParam;
case WM_CTLCOLORSTATIC:
SetTextColor(hdcStatic, RGB(0, 0, 150));
SetBkColor(hdcStatic, RGB(0, 230, 0));
return (INT_PTR)CreateSolidBrush(RGB(255, 0255, 255));
break;
I know it gets applied to wParam which is the whole thing..
But I want to apply it to 1 single HWND called (txtview1) not to txtview2 too
I tried:
HDC hdcStatic = GetDC(txtview1);
but it doesn't take affect, any hint is much appreciated.
You need to handle this message with checking if lParam equals to HWND you need
if ( (HWND)lParam == txtview1 )
Otherwise, just fall back to DefWindowProc
Related
I created the dialog form for MFC class by editing .rc file with form designer as follows,
It is taken as LTEXT. I want to change the color of that text using WM_CTLCOLORSTATIC message.
I used the subclass as follows,
HWND name_message = ::GetDlgItem(hwnd_, IDC_EDIT_OUTPUT_STRING);
g_EditTxtViewWndProc = (WNDPROC)(LONG_PTR)GetWindowLongPtr(name_message, GWLP_WNDPROC);
SetWindowLongPtr(name_message, GWLP_WNDPROC, (LONG_PTR)(EditTxtViewProc));
LRESULT CALLBACK
EditTxtViewProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
static HBRUSH hBrush = CreateSolidBrush(RGB(255, 0, 0));
switch( msg )
{
case WM_CTLCOLORSTATIC:
{
HDC hdC = (HDC)wp;
SetTextColor(hdC, RGB(255, 0, 0));
SetBkColor(hdC, RGB(255, 255, 255));
return (INT_PTR)hBrush;
}
}
}
In above case it does not call to the WM_CTLCOLORSTATIC message. I am beginner to the Window Programming.
Can anyone help me that how to subclass as above?
Remy Lebeau's comment is correct. You need to handle this message from within the parent's window procedure.
In MFC, you could also directly use CWnd::OnCtlColor. Most controls send this message to their parent (usually a dialog box) to prepare the pDC for drawing the control using the correct colors.
For more information, refer to MSDN: https://learn.microsoft.com/en-us/cpp/mfc/reference/cwnd-class#onctlcolor
I've just created multiple edit boxes (11x11 controls) based on this article:
https://msdn.microsoft.com/en-us/library/windows/desktop/hh298433%28v=vs.85%29.aspx
Well, not exactly same, but I used the code in case WM_CREATE: block to create huge number of controls.
I use this dialog process on the parent window:
INT_PTR CALLBACK StartupDialogProc(HWND dialog, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg){
case WM_INITDIALOG:
Init_Startup(dialog);
return 1;
/*
case EN_CHANGE:
case WM_CTLCOLOREDIT:
{
HDC hdC = (HDC)wParam;
COLORREF crColorBackground = RGB(255,0,0);
if (crColorBackground)
SetBkColor(hdC, crColorBackground);
SetTextColor( hdC, RGB(12,112,212) );
SetBkMode( hdC, TRANSPARENT );
RECT rect;
GetClientRect( (HWND)lParam, &rect );
HBRUSH hBrush = CreateSolidBrush( RGB(209,209,209) );
//FrameRect( hdC, &rect, hBrush );
Rectangle( hdC, (int)rect.left, (int)rect.top, (int)rect.right, (int)rect.bottom );
DeleteObject( hBrush );
LOGBRUSH lb;
lb.lbStyle = BS_SOLID;
lb.lbColor = RGB(249,249,249);
lb.lbHatch = 0;
CreateBrushIndirect(&lb); // LRESULT
// GetStockObject(NULL_BRUSH);
return 1;
}
break;
*/
case WM_DESTROY:
setts.options.page = GetDlgItemInt(dialog, IDC_O_STARTUP_PAGE, NULL, FALSE);
setts.options.recent = GetDlgItemInt(dialog, IDC_O_STARTUP_RECENT, NULL, FALSE);
break;
case WM_CLOSE:
EndDialog(dialog, FALSE);
break;
case WM_COMMAND:
if (wParam == IDOK) {
EndDialog(dialog, TRUE);
return 0;
}
}
return 0;
}
There is few things unclear to me:
1) if I would like to change color of border for all edit controls from id 5001 to id 5121, how to do that? To me, the commented code does not work (when would it be uncommented). It looks like I have this in incorrect place.
2) how correctly create the dialog processes to all the controls? Because there is big number and could be yet few times higher, should I just call a loop from 5001 to id 5121 and call the function:
INT_PTR CALLBACK EditDlgProc(HWND dialog, UINT msg, WPARAM wParam, LPARAM lParam) - that won't work, because every function would need to have different name.
To change the border color of edit control, you have to subclass the edit control and override WM_NCPAINT. That's a little advanced, and you don't really need it. You can just use WS_EX_CLIENTEDGE flag:
CreateWindowEx(WS_EX_CLIENTEDGE, L"EDIT" ...
Also make sure project manifest is setup so you get modern window's look.
This would be an error if it had not been commented out:
case EN_CHANGE:
case WM_CTLCOLOREDIT:
Each case should end in break; or return 0;
Moreover, WM_CTLCOLOREDIT should return a brush which was created on heap. It should not return 1. See documentation :
There are also other errors in that section, you should just get rid of that. See this example for painting.
On my WIN32 dialog box I draw a circle (Bitmap resource) and I want to have an image located near it.
I am not able to force the cursor to be on top of the circle image:
I draw both circle and cursor as static windows:
Circle:
HWND hRingImage= CreateStatics(m_hDlg, hInst, SS_BITMAP | WS_BORDER, rc, m_ID, L"");
HANDLE hRingImage1 = LoadImage(hInst, MAKEINTRESOURCE(IDB_RING50), IMAGE_BITMAP,m_Radius*2, m_Radius*2, LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS );
SendMessage(hRingImage,STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hRingImage1);
m_hRingImage = hRingImage;
if (!Enabled)
ShowWindow(hRingImage, SW_HIDE);
Red Cursor:
m_hIndicator= CreateStatics(m_hDlg, GetModuleHandle(NULL), SS_ICON , rc, m_ID+10, L"");
HANDLE hRingImage1 = LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_INDICATOR), IMAGE_CURSOR,8, 8, LR_DEFAULTSIZE|LR_SHARED );
SendMessage(m_hIndicator,STM_SETIMAGE, IMAGE_CURSOR, (LPARAM)hRingImage1);
SetWindowPos(m_hIndicator, HWND_TOPMOST, 0,0,0,0, SWP_NOMOVE|SWP_NOSIZE);
ShowWindow(m_hIndicator, SW_SHOW);
I can't see what makes the circle topmost while the cursors are always at the bottom (strange, they also under the dialog box frame lines.
You can set the cursor manualy:
First load the cursor image-> HCURSOR hCursorRing = LoadCursor(...);
BOOL CALLBACK DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam){
switch (message){
case WM_CLOSE:
DestroyWindow(hDlg);
break ;
case WM_SETCURSOR:
if((HWND)wParam == hRingImage){
SetCursor(hCursorRing);
return true;
}
break ;
default: //for messages that we don't deal with
return false;
}
return false;
}
valter
I had to do the following:
ShowWindow(m_hIndicator, SW_HIDE);
MoveWindow(m_hIndicator, loc.x-3,loc.y-3,8,8, TRUE);
ShowWindow(m_hIndicator, SW_SHOW);
The "cursor" which is actually just a bitmap is located correctly on top of all other bitmaps.
I apologize for the vagueness of the title, but i'm not entirely sure how i want to go about solving the issue at hand. Basically, i have 2 groups of buttons. When the user selects a button from one of the groups, i want to set an indicator that that group has been selected. So either a rectangle surrounding them (in blue) or coloring the background (or background image) behind the group. The end user indicated that a rectangle surrounding them would be nice so that would be preferential. I have tried overriding the onCtlColor on a group box, but I don't know how to limit the coloring to just the border. I do know that it absolutely needs to be the farthest back in z-order Any advice?
Example code (i'm aware that it pains the entirety of the box)
pDC->SetBkColor(GetSysColor(RGB(100,149,237)));
CRect rect;
testGb.GetClientRect(rect);
CBrush brushBlue(RGB(0, 0, 255));
CBrush* pOldBrush = pDC->SelectObject(&brushBlue);
pDC->Rectangle(rect);
pDC->SelectObject(pOldBrush);
I could find only a way to change the background colour of the Text of a group box:
EDIT You can paint anything you want on the Group box!
a) Declare a CBrush member variable m_br and create a coloured brush with it
b) Override WindowProc for a group box with ID = IDC_GROUPBOX:
LRESULT CTestMFCDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{ if (message == WM_CTLCOLORSTATIC)
if (::GetDlgCtrlID((HWND) lParam) == IDC_GROUPBOX)
return (LRESULT) m_br.GetSafeHandle();
return CDialogEx::WindowProc(message, wParam, lParam);
}
LRESULT CTestMFCDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{ if (message == WM_CTLCOLORSTATIC)
if (::GetDlgCtrlID((HWND) lParam) == IDC_GROUPBOX)
{ HWND hWnd = (HWND) lParam;
HDC hDC = (HDC) wParam;
RECT rc;
::GetClientRect(hWnd, &rc);
HBRUSH hOldBrush = (HBRUSH) ::SelectObject(hDC, m_br);
::Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);
::SelectObject(hDC, hOldBrush);
// return (LRESULT) m_br.GetSafeHandle();
}
return CDialogEx::WindowProc(message, wParam, lParam);
}
Better code (at least for me):
void MyClass::OnPaint()
{
CPaintDC dc(this); // device context for painting
COLORREF highlightFillColor;
CPen nPen, *pOldPen = NULL;
CBrush nBrush, *pOldBrush = NULL;
CRect rect;
GetWindowRect(rect);
ScreenToClient(rect);
BmsMemDC memDc(&dc, &rect);
memDc.SetBkMode(TRANSPARENT);
//dc.Re
highlightFillColor = RGB(0x99,0xB4,0xFF);
nPen.CreatePen( PS_SOLID, 4, highlightFillColor);
nBrush.CreateSolidBrush( GetSysColor(COLOR_3DFACE ));
pOldPen = memDc.SelectObject(&nPen);
pOldBrush = memDc.SelectObject(&nBrush);
if(leftGroupSelected)
{
rect.SetRect(rect.left + 4, rect.top+30, rect.left + 126, rect.bottom - 5);
memDc.FillRect(&rect,&nBrush);
memDc.RoundRect(rect.left, rect.top, rect.right, rect.bottom, 8, 8);
}
if (rightGroupSelected)
{
rect.SetRect(rect.left + 134, rect.top+30, rect.left + 256, rect.bottom - 5);
memDc.FillRect(&rect,&nBrush);
memDc.RoundRect(rect.left, rect.top, rect.right, rect.bottom, 8, 8);
}
}
I have Created a static control using following styles...
picBoxDisp = CreateWindow("STATIC", "image box",
WS_VISIBLE |WS_CHILD | SS_BITMAP |WS_TABSTOP | WS_BORDER,
50, 50, 250, 300,
hwnd , (HMENU)10000, NULL, NULL);
SetWindowLongPtr(picBoxDisp,GWLP_WNDPROC,(LONG) dispWndProc);
from someplace in my program I have the following code..
SendMessage(picBoxDisp,STM_SETIMAGE, (WPARAM) IMAGE_BITMAP,(LPARAM) hBitmap);
now inside the dispWndProc I have the following code..
LRESULT CALLBACK dispWndProc(HWND hwnd,UINT msg, WPARAM wParam, LPARAM lParam)
{
static HDC hdc;
static PAINTSTRUCT paintSt;
static RECT aRect;
switch(msg)
{
case WM_PAINT:
{
hdc = BeginPaint(hwnd,&paintSt);
GetClientRect(hwnd,&aRect);
// the code for painting
EndPaint(hwnd,&paintSt);
}
break;
case STM_SETIMAGE:
{
//painting code;
HBITMAP img = (HBITMAP)lParam;
BITMAP bmp;
GetObject(img,sizeof(bmp),&bmp);
HDC imgDC = GetDC((HWND)img);
HDC memDC = CreateCompatibleDC(imgDC);
SelectObject(memDC,img);
if((img==NULL))// ||(imgDC==NULL)||(memDC==NULL))
{
MessageBox(NULL,"img is NULL","Bad Programming!!! Error",MB_OK);
}
else
{
StretchBlt(hdc,0,0,aRect.right,aRect.bottom,
memDC,0,0,bmp.bmWidth,bmp.bmHeight,
SRCCOPY);
}
}
break;
default:
return DefWindowProc(hwnd,msg,wParam,lParam);
}
return 0;
}
can anyone tell why the lParam doesnt typecast back to HBITMAP.... why img is NULL ?
thanks in advance,
It's possible that some other code is also sending STM_SETIMAGE to your window. Count the number of times you call SendMessage(STM_SETIMAGE) and the number of times you reach case STM_SETIMAGE.
Also, HDC imgDC = GetDC((HWND)img); is never going to work. An HBITMAP is not an HWND.
There are multiple issues with this code.
You cannot use BeginPaint / EndPaint anywhere except for handling WM_PAINT. Fix that before even considering other problems.
Next, it's not clear that you're correctly subclassing the window; make sure you call CallWindowProc on the old window proc.
It's tricky to guarantee that what you are seeing is really what you think you are seeing. For example as Ben Voigt says, maybe you are not the one that sent it. Maybe a switch case block above fell through. Maybe you passed in NULL to begin with.
Start with these things, and you will get closer to being on track.