Win32 Button doesn't properly display in a Direct2D Window - c++

I have a Direct2D program, and my goal is to have a Win32 button rendered with the Direct2D window.
I was able to compile the program fine, but the problem is that the button only shows when I click on it. Once I click outside of the button, it just goes invisible. It's even invisible when I open the application. What I expect is for the button to be visible all the time. I'm not necessarily worried about if it renders above or below the Direct2D renderer.
When I click on it:
When I click outside the button (just blank):
Here is my render function:
create_drs(); // Creates device resources
m_pRenderTarget->BeginDraw();
m_pRenderTarget->Clear(D2D1::ColorF(bg.r / 255, bg.g / 255, bg.b / 255, 1));
HWND hwndButton = CreateWindow(
L"BUTTON",
L"a button",
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
0,
0,
150,
150,
m_hwnd,
NULL,
(HINSTANCE)GetWindowLongPtr(m_hwnd, GWLP_HINSTANCE),
NULL);
m_pRenderTarget->EndDraw();
I've tried taking out the Clear function, but it's still invisible when the application opens, but stays visible forever once I click on it. I also tried looking online, but couldn't find a sufficient solution for this specific problem.

Related

Winapi c++ make static image behave like a button (Hover, Click)

I want to change a Static bitmap image when hovering it. I've tried using a button instead, but the picture never fill the button. I've tried too TrackMouseEvent but I want it to be always active so i cannot use this. Is there a way to get notified when mouse hover a static control or to make a control that behaves like that?
This is my control:
HWND Button = CreateWindow("Static", NULL,
WS_VISIBLE | WS_CHILD | SS_BITMAP | SS_NOTIFY,
20, 240, 120, 20,
hwnd, (HMENU)101, NULL, NULL);
SendMessage(hwnd, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)view.vBitMap);
I use SS_NOTIFY nto get notified when user clicks it or doubleclicks it, but unlike BS_NOTIFY, it don't tell when hovering on WM_NOTIFY

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:

WINAPI Button background

In WINAPI, I create a button like:
case WM_CREATE:
{
Start = CreateWindowEx(WS_EX_TRANSPARENT, "Button", "Start", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 20, 50, 75, 25, window, (HMENU)ID_START, hInstance, NULL);
break;
}
The button looks like:
But I need it to look like this one (which I did in .Net):
How can I get rid of that black border/background?
Start = CreateWindowEx(WS_EX_TRANSPARENT, ...);
You got the black outline because you used the WS_EX_TRANSPARENT style flag. It isn't clear why you used it, there's not much you can do with it when you use the Button control. It is otherwise probably the least understood style flag. Pass 0 instead to get a normal looking button.
It is otherwise a lost cause to get the exact look of a .NET button, Winforms doesn't use the built-in Button control. It creates its own, using a custom renderer to get the gradient look. Reproducing that native code is a lot of work.
I think the border you are seeing is because the button has the "Default Button" property. If you turn that off, then it will have a normal border. The Default property just tells Win32 which button to activate if the users hits ENTER on the dialog/form. If you only have one button, then it will always have the default property. If you add a second, it will not.
The property is the BS_DEFPUSHBUTTON property, so in your CreateWindowEx call, you should be able to do something like:
Start = CreateWindowEx(WS_EX_TRANSPARENT, "Button", "Start", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | ~BS_DEFPUSHBUTTON, 20, 50, 75, 25, window, (HMENU)ID_START, hInstance, NULL);
If not, you'll have to set it with ModifyStyle or ModifyStyleEx, and pass it in the "Remove" parameter. I forget which one the specific styles have to be passed in, but if I recall correctly, it's the normal style params, NOT the EX params.
I haven't tested this, but try creating the button like this:
Start = CreateWindowEx(0, WC_BUTTON, "Start", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_TEXT, 20, 50, 75, 25, window, (HMENU)ID_START, hInstance, NULL);
break;
It also might depend on how you've created your main window. Can you post the code for your main window creation?
EDIT: I mis-identified the border as the default-button border. As David Hefferman pointed out, it's not. That is, I have now reproduced that border effect; when the program starts there is no border, but just a little mousing over the left button creates the border – at least in Windows 7.
Original answer follows:
The black border is because it's default. You shouldn't interfere with the system's visualization of default buttons etc. Users rely on those cues.
To change the font, maybe, like, WM_SETFONT?
Disclaimer: I haven't tried that. It might be you need to handle WM_CTRLCOLOR or something like that. Just try it out, and in the end, if the default buttons don't cut it for you, simply implement your own button.

Groupbox Font Issue with WinAPI

I have problems with creating a simple Group-Box-Control via CreateWindowEx. The font-size/-style of its caption just doesn’t look right.
I have created a simple Windows Dialog (containing group-boxes, buttons…) with the Visual Studio - Resource Manager. When I load that dialog with DialogBox(…) everything looks normal but when I create another group-box-control on that same dialog via CreateWindowEx(…) the caption of the new control has a different font-size/-style.
With Microsoft Spy++ I was able to see the dwExStyle and dwStyle values of the other groub-boxes, but even when I use the same values in CreateWindowEx I still get a different look.
Here is the code I use to create the new group-box:
HWND hGroup1 = GetDlgItem(_hWnd, IDC_GROUPBOX1);
HWND hGroup2 = CreateWindowEx(
WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_NOPARENTNOTIFY,
L"Button",
L"Hallo",
WS_CHILDWINDOW | WS_VISIBLE | BS_GROUPBOX,
20, 20, 250, 250,
hGroup1,
nullptr,
_hInstance,
nullptr);
Here is a screen capture of the dialog:
http://imageshack.us/photo/my-images/856/groupboxfontissue.png/
Please let me know where I went wrong and what I can do to fix it.
[EDIT-1]
In regards to Jonathan Potter and Superman, as you suggested I set the font-handle of the new group-box to the same as for the other controls.
HFONT hFont1 = (HFONT)SendMessage(hGroup1, WM_GETFONT, 0, 0);
HFONT hFont2 = (HFONT)SendMessage(hGroup2, WM_GETFONT, 0, 0);
HFONT hFont3 = (HFONT)SendMessage(_hWnd, WM_GETFONT, 0, 0);
SendMessage(hGroup2, WM_SETFONT, (WPARAM)hFont1, TRUE);
hFont2 = (HFONT)SendMessage(hGroup2, WM_GETFONT, 0, 0);
At the end of this code, I can see that all controls and the dialog window have the same font-handle but only the controls which were created with the Resource Manager have the correct font (which is the system font).
Is there anything else I can do???
[EDIT-2]
I cannot believe it… it works now! Thank you all very much for your help!
I just had to set the hWndParent value in CreateWindowEx(…) to the dialog handle and then use WM_GETFONT and WM_SETFONT to copy the right font.
I wish you all a nice weekend.
Controls you create manually (via CreateWindowEx) do not get their font set automatically, and will default to the "system font" (which is what you see in your screenshot). Instead, you need to set the control's font once it has been created. For example,
SendMessage(hGroup2, WM_SETFONT, (WPARAM)SendMessage(hGroup1, WM_GETFONT, 0, 0), TRUE);
When you place a control in a dialog using the resource editor, the font set to the dialog, which is the parent of the control will be used for it by default.
If you're creating a control dynamically, the system font will be used instead of the font of the dialog.
To get the same font of the dialog for a control that you create dynamically, set the font of the dialog to the control in the WM_INITDIALOG handler.
In the code snippet below, replace m_hWnd with the handle of the parent dialog.
HFONT font = (HFONT)::SendMessage(m_hWnd, WM_GETFONT, 0, 0);
::SendMessage(hGroup2, WM_SETFONT, (WPARAM)font, TRUE);

List Control SetFocus Redraw Error on a Tab Control

Environment: Visual Studio 2008, Visual Studio Feature Pack, MFC Dialog App, Windows XP, New Common Controls.
I'm having a problem with a list control that happens to be on a tab control.
To reproduce the problem simply create a dialog based app. Place a tab control on that dialog, then put a list control onto that tab control. You don't need to add any code to the project. Just build and run. Set the focus to the list view and then either minimize the dialog or bring another window in front of it.
Now bring the dialog back to the foreground, the list will not draw itself correctly.
One thing I have tried is handle the set focus event for the list control, but left it with an empty method body, ie...
void CMyListControl::OnSetFocus(CWnd* window)
{
// Default();
}
Then the redraw problem goes away, however now you can not select items within the list. Uncommenting the call to Default makes the problem come back.
If I move the list off of the tab the problem goes away. If I set the focus to another control on the tab or dialog, the problem goes away. This is a weird one.
In fact, if you watch closely you can see the list drawing itself and then being obscured by the tab control.
I know it's late but I had them same problem today. You need to set ListView's parent to Tab control.
hWndTab = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TABCONTROL, NULL,
WS_CHILD | WS_TABSTOP | WS_VISIBLE,
0, 0, 0, 0, hWnd, (HMENU) IDC_TAB, hInstance, NULL);
hWndList = CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTVIEW, NULL,
WS_CHILD | WS_TABSTOP | WS_VISIBLE | LVS_REPORT,
0, 0, 0, 0, hWndTab, (HMENU) IDC_LIST, hInstance, NULL);
Note parent window handler for hWndList: hWndTab. Or you can use SetParent.