I have noticed a strange effect when I create a Listview.
When I create a ListView without also creating a Button, the selected item in the ListView have a dotted border. However, when I also create a Button, the ListView selected item don't have a dotted border anymore. This only happens when I have a manifest file that enables common controls 6:
This is the code I used to create the Window and ListView and Button:
// Create Window
HWND hWnd = CreateWindowEx(0, "WinClass", "My Window", WS_OVERLAPPEDWINDOW, 261, 172, 394, 284, NULL, NULL, hInstance, NULL);
// Create ListView
HWND hListView = CreateWindowEx(0, WC_LISTVIEW, "", WS_CHILD | LVS_REPORT | WS_VISIBLE, 0, 0, 232, 190, hWnd, 0, GetModuleHandle(NULL), NULL);
// Create Button
HWND hButtonRefresh = CreateWindowEx(NULL, "BUTTON", "OK", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 10, 200, 110, 25, hWnd, NULL, GetModuleHandle(NULL), NULL);
Note: I don't have a problem with this effect, I just want to understand why it is happening!
It's just because the button has the focus and the list view lost it, click on the list view and the dots should reappear.
I believe the dotted border is indicating the default control. In the second screenshot go to the Properties of the button and set Default Button to false and then you should see the dotted border around the text like in the first screenshot.
To do this open the dialog in Resources view, select the button and choose Properties from the right-button mouse menu. In the Properties window you should see Default Button in the Behavior section - just change it to False.
Alternatively in code try something like this:-
DWORD style = m_BtnOk.GetStyle();
// remove default push button style
style &= ~BS_DEFPUSHBUTTON;
// set the style
::SendMessage(m_BtnClose.GetSafeHwnd(), BM_SETSTYLE, (WPARAM)style, (LPARAM)TRUE);
As others have indicated, it's purpose is to indicate input focus. If you Tab around any native form, you'll see the rectangle jump around the indexes set up by the developer.
The reason it appears at all is because it has a TabStop. As there is only one element in the first example, there's only one possibility for a tab stop, so it's indicated by the rectangle. Play around with the TabStop property, Tab around, see what changes.
Related
I'm noticing that standard edit controls are not showing the last line of text if it's not fully visible. Is there a way to override this behavior? If not, is there an equivalent solution to an edit box that does? Preferably in "pure" Win32 API fashion, as I am not using MFC or ATL. This is how I define the edit control at the moment:
CreateWindow(L"EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE, 0, 0, 0, 0, hWnd, (HMENU)ID_EDIT_CONTROL, hInst, NULL);
How do I make an Edit Control have its width and height as 100% of the window.
A good example of this is the Edit Control in Notepad.
Up till now, I've been setting the size of controls in the CreateWindow() function as static integers.
e.g.
CreateWindow("EDIT", NULL, WS_CHILD | WS_VISIBLE,
0, 0, 640, 480, hWnd, NULL, NULL, NULL);
I am using C and Visual Studio 2015.
Thanks in advance.
You have to handle WM_SIZE messages in your main window procedure and use SetWindowPos API call to resize an edit control.
So I have a groupbox-style button. I can put a button inside it by creating a button with the groupbox as the parent. However, if I do that, the groupbox gets the button-click message instead of the window. Is there any way I can intercept these messages or have them forwarded on?
There is an example on PasteBin, where instead of putting the button in the groupbox they hover it over the top, however this means that I can't simply make the groupbox and its contents invisible in one command (and it's cheating, so is likely to go wrong at some point). So, is there a way to do it where the button is actually in the groupbox?
Example code to create the controls:
HWND hSoFGrp = CreateWindowEx(WS_EX_LEFT, "BUTTON", _T("Group Text"), WS_CHILD | WS_TABSTOP | WS_VISIBLE |
BS_GROUPBOX | BS_TEXT | BS_LEFT | BS_TOP,
0, 250, 150, 100, hwnd, (HMENU) 40,
GetModuleHandle(NULL), NULL);
HWND hSoFBtn = CreateWindowEx(WS_EX_STATICEDGE, "BUTTON", _T("Button"), WS_CHILD | WS_TABSTOP | WS_VISIBLE |
BS_PUSHBUTTON | BS_CENTER | BS_TEXT | BS_VCENTER | BS_MULTILINE,
100, 15, 48, 30, hSoFGrp, (HMENU) 41,
GetModuleHandle(NULL), NULL);
Example code to handle the messages:
switch (msg)
{
case WM_COMMAND:
if (LOWORD(wParam) == 40)
{
//This would be messages from the groupbox
}
else if (LOWORD(wParam) == 41)
{
//This would be messages from the button if the groupbox wasn't intercepting them!
}
break;
}
So, is it possible?
Group boxes are typically not used as parent windows to the controls visibly contained within them. The hierarchical structure of HWNDs does not necessarily match the visible organization of controls. Instead you should make the group box a sibling of its grouped controls.
Note that the group box should be positioned immediately before (above) its grouped controls in z-order; that way activating the mnemonic from the group box label will move focus to the first control in the group. Even though the group box control will be above its grouped controls, a group box explicitly allows other controls to draw themselves over it.
With C#, I was easily able to get the effect I wanted:
However, I'm having trouble doing the same thing using the Win32 API in C. I don't know how to create a window that has no icon (at all), but still has a caption, a minimize button, and a close button.
I registered my class properly, but I can't figure out what to put for the window styles/extended window styles.
static const TCHAR lpctszTitle[] = TEXT("Stuff"), lpctszClass[] =
TEXT("StuffClass");
HWND hWnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOPMOST, lpctszClass,
lpctszTitle, WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX,
CW_USEDEFAULT, 0, 250, 55, NULL, NULL, hThisInstance, NULL);
The code above produced:
which still has an icon in the title bar and is not what I wanted.
A standard window requires an icon because it needs some form of representation in the taskbar at the bottom of the screen. What should be displayed when you press Alt+Tab in the window switcher if one of the main windows doesn't have an icon?
You need to specify the WS_EX_DLGMODALFRAME extended style. This is the same effect that WinForms sets when you turn off the icon in the title bar.
You also need to make sure that you do not specify an icon when you register the window class. You need to set the hIcon and hIconSm fields of the WNDCLASSEX structure to 0.
Change your code to the following:
static const TCHAR lpctszTitle[] = TEXT("Stuff"), lpctszClass[] =
TEXT("StuffClass");
HWND hWnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOPMOST, lpctszClass,
lpctszTitle, WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX,
CW_USEDEFAULT, 0, 250, 55, NULL, NULL, hThisInstance, NULL);
On a side note, use Spy++ or other similar tool to see the styles that any given HWND actually uses. Point it at your C# window, then duplicate the reported styles in your C code.
When I enable common control visual style support (InitCommonControls()) and I am using any theme other then Windows Classic Theme, buttons inside a group box appear with a black border with square corners.
Windows Classic Theme appears normal, as well as when I turn off visual styling.
I am using the following code:
group_box = CreateWindow(TEXT("BUTTON"), TEXT("BS_GROUPBOX"),
WS_CHILD | WS_VISIBLE | BS_GROUPBOX | WS_GROUP,
10, 10, 200, 300,
hwnd, NULL, hInstance, 0);
push_button = CreateWindow(TEXT("BUTTON"), TEXT("BS_PUSHBUTTON"),
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
40, 40, 100, 22,
group_box, NULL, hInstance, 0);
EDIT: The issue occurs with radio buttons as well
EDIT: I am not using any dialogs/resources, only CreateWindow/Ex.
I am compiling under Visual C++ 2008 Express SP1, with a generic manifest file
Screenshot http://img.ispankcode.com/black_border_issue.png
The problem is having the groupbox as the controls' parent. Groupboxes are not supposed to have any children and using them as parents will cause all kinds of errors (including painting, keyboard navigation and message propagation). Just change the parent in the buttons' CreateWindow call from group_box to hwnd (i.e. the dialog).
I'm guessing you used the groupbox as the parent in order to position the other controls easily inside it. The proper way to do this is to get the position of the groupbox client area and map it to the client area of the dialog. Everything placed in the resulting RECT will then appear inside the groupbox. Since groupboxes don't actually have a client area, it can be calculated with something like this:
// Calculate the client area of a dialog that corresponds to the perceived
// client area of a groupbox control. An extra padding in dialog units can
// be specified (preferably in multiples of 4).
//
RECT getClientAreaInGroupBox(HWND dlg, int id, int padding = 0) {
HWND group = GetDlgItem(dlg, id);
RECT rc;
GetWindowRect(group, &rc);
MapWindowPoints(0, dlg, (POINT*)&rc, 2);
// Note that the top DUs should be 9 to completely avoid overlapping the
// groupbox label, but 8 is used instead for better alignment on a 4x4
// design grid.
RECT border = { 4, 8, 4, 4 };
OffsetRect(&border, padding, padding);
MapDialogRect(dlg, &border);
rc.left += border.left;
rc.right -= border.right;
rc.top += border.top;
rc.bottom -= border.bottom;
return rc;
}
Note that the same applies to Tab controls. They too are not designed to be parents and will exhibit similar behavior.
Just a guess here, but it looks like you are inheriting either the Static Edge or Client Edge style from you theme. I create most of my dialogs from the resource editor and set these properties there.
In your case, you can replace your CreateWindow with a CreateWindowEx to set these extended styles, which are probably being defaulted in CreateWindow. Specifically check out WS_EX_STATICEDGE, WS_EX_WINDOWEDGE and WS_EX_CLIENTEDGE
Edit: I'm assuming that this is not happening because you button is the default control in the dialog, which would also give a black edge.
Apparently group boxes are not meant to group controls (be a parent hwnd)
So in order to get rid of the black borders/painting issues I would have to subclass group box and implement WM_PAINT and WM_PRINTCLIENT
Ahh yes the black background with radio buttons and group boxes. Although I'm not sure if this will work for VC++ 2008, but back-in-the-day the solution for VB6 themed apps was to put the radio controls on a PictureBox (a generic container really) first and then add that to the group box.
Its worth a shot!