MFC Add thin border to WS_CHILD window - mfc

How can I add border to an embedded child window with (WS_CHILD | DS_CONTROL) style hosed by a CFormView?
I have tried to add border in Dialog Editor by selecting Thin border type but it doesn't work.
I also tried SetWindowLong and ModifyStyle. But the result is, WS_BORDER style is added but still no border.
Is it possible to add border to embedded child window by choosing styles? or should I draw it myself?
Thanks,
Guan

As #IInspectable points out, passing SWP_DRAWFRAME to SetWindowPos is required after changing the window styles.
I finally choose ModifyStyle to add WS_BORDER to my WS_CHILD window and pass SWP_DRAWFRAME flag to the third parameter: m_wndMainPage.ModifyStyle(0, WS_BORDER, SWP_DRAWFRAME). It internally calls SetWindowPos and update the child window. Window border is drawn as expected.

Related

Maximized WS_POPUP window goes in front of the taskbar

I'm creating a window in C++ with that code:
HWnd = CreateWindow(wc.lpszClassName,
"myapp",
WS_POPUP |WS_VISIBLE,
10, 10, 1000, 800, 0, 0, hInst, NULL);
It appears as I want but when I maximize it with like this:
ShowWindow(hwnd, SW_SHOWMAXIMIZED);
then it's like a fullscreen window so that the taskbar is hidden.
I think it's because it is a POPUP window but this is like I want it to appear.
Do I need to create my own maximize function or is there a parameter to avoid that ?
Thanks
You can add WS_CAPTION | WS_SYSMENU | WS_MAXIMIZEBOX style.
If you want your window to be without caption then you will need to adjust window size manually to fit into desktop work area that you can query using SystemParametersInfo specifying SPI_GETWORKAREA flag.
This is a feature where the Taskbar will get out of your full-screen application:
If you want to create a fullscreen window that covers the taskbar, just create a fullscreen window and the taskbar will automatically get out of the way.
I’ve seen people hunt for the taskbar window and then do a ShowWindow(hwndTaskbar, SW_HIDE) on it. This is nuts for many reasons.
Don’t do any of this messing with the taskbar. Just create your fullscreen window and let the taskbar do its thing automatically.
Since this is Stackoverflow, a combination of Wikipedia and Reddit, i want this relevant information saved for the next guy asking this question.

c++ MFC Window(Frame) Manipulation

I'm working on an Windows Application which has to show an overlaying fixed positioned window ("PopUp") in the left corner of the MainFrame which will receive some Information if a user missed some input or if certain actions have been successfully.
The "PopUp" Titlebar shall have an Icon next to the Title (e.g. ->Icon<- "Error") and the standard X - Close-Button. The ClientArea will have an descriptive text of the occurred Message.
Additionally the standard Border of the PopUp shall be set to 1px(smaller than the default windows border)
The "PopUp" is derived from CWnd and created with WS_VISLBE | WS_CLIPSIBLINGS | WS_CHILD | WS_CAPTION in the OnCreate-Method of the Applications MainFrame Window
Now I need to set/shrink the default Border of my PopUp and add the Icon to the Titlebar of the PopUp.
Can someone give me some example code of how i can solve my issues?
I'm pretty new to c++ and MFC so far my research brought me to https://msdn.microsoft.com/en-us/library/windows/desktop/bb688195(v=vs.85).aspx
but i dont know where and how to use DwmExtendFrameIntoClientArea() but so far I've read I assume Dwm is the way to go to be able to solve both problems or is there another/totally different way? Am I on the right track?
Finally I was able to shrinkthe default Windows Border by overriding the handling of WM_NCCALCSIZE.
I will update this answer as soon as I solved how to put my Icon in the Titlebar.
As of now I'll explain how I shrink the windows border:
Add ON_WM_NCCALCSIZE() to your MessageMap of the desired Window and Implement OnNcCalcSize() (Class Wizard will help to set this up) as followed:
void YourCWndClass::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp)
{
if (bCalcValidRects){
CRect rcClient, rcWind;
GetClientRect(&rcClient);
GetWindowRect(&rcWind);
int border = (rcWind.right - rcWind.left - rcClient.right) / 2 - 1;
//-1: leaves 1px of the Windows Default Border Width erase to have no border
lpncsp->rgrc->left -= border;
lpncsp->rgrc->right += border;
lpncsp->rgrc->bottom += border;
}
CWnd::OnNcCalcSize(bCalcValidRects, lpncsp);
}
The WM_NCCALCSIZE Message is sent up on the Window Creation (when you call Create()/CreateEx() ) but at this point of time GetClientRect() and GetWindowRect() will not return the proper values therefore you need to check the Bool Parameter!!!
To trigger another WM_NCCALCSIZE to be able to work with the proper Window Rectangles call SetWindowPos() right after the window creation
if (!m_MessagePopOver->Create(NULL, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_CAPTION, rect, this, NULL, NULL)){
TRACE0("failed to create MessagePopOver");
}
m_MessagePopOver->SetWindowPos(&wndTop, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
This will result in a window like this:

Groupbox resizing issue with radio buttons on top

I'm not sure what I'm doing wrong here. I'm trying to implement a resizing dialog window using MFC. The code is pretty straightforward. I override the following sizing notification:
void CMyDlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
//...
//First move the groupbox, pGroupbox is of type CWnd
pGroupbox->MoveWindow(rcGroupbox);
//And then move all radio buttons in it
//Each is moved the exact same way
//pEachRadioButton is of type CWnd
pEachRadioButton->MoveWindow(rcEachRadioButton);
}
But what I get as a result is this.
First here's the initial groupbox:
It happens only when I start dragging the bottom of the main window frame down. I get this artifact:
Note that the radio button positions themselves are correct. If I move the mouse over either of them, it redraws itself correctly (like this "shut-down" button):
Here's the layout of the dialog itself:
IDD_MY_DIALOG DIALOGEX 0, 0, 437, 190
STYLE DS_SETFONT | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
EXSTYLE WS_EX_APPWINDOW
CAPTION "My dialog"
MENU IDR_MENU_MAIN
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
PUSHBUTTON "&Cancel",IDCANCEL,381,169,50,14
GROUPBOX "When Tasks Are Completed",IDC_STATIC_WHEN_COMPLETED,7,113,423,36
CONTROL "Close the pro&gram",IDC_RADIO_CLOSE_PROGRAM,"Button",BS_AUTORADIOBUTTON | WS_GROUP,26,129,73,8
CONTROL "Put computer to sleep",IDC_RADIO_SLEEP,"Button",BS_AUTORADIOBUTTON,122,129,84,10
CONTROL "Hibernate computer",IDC_RADIO_HIBERNATE,"Button",BS_AUTORADIOBUTTON,229,129,78,10
CONTROL "Shut down computer",IDC_RADIO_SHUT_DOWN,"Button",BS_AUTORADIOBUTTON,330,129,81,10
DEFPUSHBUTTON "&OK",IDC_BUTTON_SET,311,161,67,22
END
I did some search and found this article, but unfortunately setting those styles did not fix the bug.
Any idea how to fix this?
PS. I'm testing it on Windows Vista, 7, or 8 with visual themes enabled.
When you move a window, the window manager will move the current image of the window as it exists. Unfortunately because you moved the frame first, all those windows got clipped. Flipping them around wouldn't help, because then the tops would get clipped.
The easy way to fix it would be to call InvalidateRect on each control after moving it.
The better way would be to call BeginDeferWindowPos before you start moving anything, then EndDeferWindowPos when you're done so that all the windows move together.
P.S. Windows prefers for the group box to come after the radio buttons in the tab order, that might make a difference too.

How to implement a re-sizable border + making it invisible using MFC?

I was wondering, how do I create a re-sizable border in MFC without showing the border itself?
IDD_GADGETTRANSLUCENTDIALOG DIALOGEX 0, 0, 320, 201
STYLE DS_SETFONT | DS_FIXEDSYS | WS_SYSMENU | WS_THICKFRAME
The "WS_THICKFRAME" style provides the functionality of resizing, but I don't want the border to be visible. How would I go about doing this?
Or handle WM_NCPAINT and draw the borders (and caption) yourself...
I created a MCF application that has the borders (and frame) as optional. When in the mode of no border, I still wanted it resizable and movable, so essentially in OnMouseMove if I was within a few pixels of the edge of the window, I set the appropriate cursor (e.g. IDC_SIZENESW for the top right corner) then if nFlags & MK_LBUTTON did a SendMessage using WM_SYSCOMMAND and the appropriate size command (e.g. SC_SIZE + WMSZ_TOPRIGHT) and let the CWnd::OnSysCommand default handler process it. Also, same trick works with SC_MOVE...

partially click through on layered windows win32

In using layered windows in win32 or atl/wtl c++ if I set the main window's alpha to 0 and paint on the child, fake window so that it is viewable and click the window, the entire window is a click through.
I want to be able to make only regions of the window click through, not the entire window, let's say if I want to paint a rounded corner window, I make the bottom/main window to be click through but I don't want the upper "fake" window to be click through, i want to be able to click on it. How do I do that?
Where I am so far:
In the OnInitDialog function of the main window :
::SetWindowLong( m_hWnd, GWL_EXSTYLE, ::GetWindowLong(m_hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
BYTE bTran = 0;
::SetLayeredWindowAttributes( m_hWnd, 0, bTran, LWA_ALPHA);
and when I create the fake window:
m_hFakeWnd = ::CreateWindowEx( WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_NOACTIVATE | WS_EX_LEFT
, m_strWndClassName
, NULL
, WS_VISIBLE | WS_OVERLAPPED
, rc.left
, rc.top
, rc.Width()
, rc.Height()
, GetSafeHwnd()
, NULL
, ::GetModuleHandle(NULL)
, NULL
);
IF, I set eliminate the WS_EX_TRANSPARENT flag the fake window is click-able while the main is click through, but! it doesn't respond to anything! click/drag. none.
It sounds like you are covering another window solely for the purpose of intercepting clicks?
Anyway, you need to handle window's WM_NCHITTEST message in order to be able to let system know that particular position is transparent, in which case you return HTTRANSPARENT:
In a window currently covered by another window in the same thread (the message will be sent to underlying windows in the same thread until one of them returns a code that is not HTTRANSPARENT).
Use alpha 1 instead of 0 in the regions you want to accept clicks. The window will still be completely invisible but the areas of alpha 1 will register clicks and mouse movements as normal.
Note that to get per-pixel alpha you'll need to use UpdateLayeredWindow rather than SetLayeredWindowAttributes.
Make two windows, one with click-through properties and another with normal ones.