winapi CreateWindowEx -> create button with user system styles? - c

I want to make a button that looks just like the OK button when you go My Computer -> Help -> About Windows.
I am creating a button like this:
hButton = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("BUTTON"), TEXT("Text"), WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, 10, 10, 30, 30, hwnd, (HMENU)IDC_MAIN_BUTTON, GetModuleHandle(NULL), NULL);
But it looks like a rough square and does not use the windows styles that the user has selected. I guess I should be using some sort of window class but I am unsure what class?

You want to use version 6 of the common controls library. To do this you need to add an application manifest to your executable. See this MSDN article on how to do that.

Try running ControlSpy which will allow you to try out different styles quickly.

Related

How to assign a variable to a control's content

HWND hStatic = CreateWindowEx( 0, "STATIC", NULL, WS_CHILD | WS_VISIBLE |
SS_LEFT, 40, 30, 150, 20, hwnd, NULL, hInstance, NULL );
SetWindowText( hStatic, "the variable" );
I am trying to learn the Windows API and am using a tutorial in my language, but it seems it does not have an answer to my question.
I would like to make a small textbox (made it this far) and make it so that I'll assign a variable to it, so that when the textbox contents change the variable is updated to hold the number entered. But I don't know how to actually connect those 2 entities.
In a console application I can use cin >>, but if I use it here it will show me the cmd instead of the window.
I didn't see anyone asking for something similar and I can't find the answer in my tutorial.
Using the Windows API, you cannot assign a variable to a control, so that it will automatically update. You will have to do this manually. The moral equivalents of cin and cout are GetWindowText and SetWindowText. Both API calls deal with character strings only. If you need the control's content as a number you have to convert it, using atoi and friends.
To be informed whenever the text in an edit control changes, the edit control's parent window's window procedure should handle the EN_CHANGE notification.

Win API, How to write text inside a dialog box?

I'm creating a small program of my own on WinAPI, (to practice the WIN API programing)
and I wanted to create an "about us" box, like where it is told who built the program, which version is it and such...
I was able to create the window sucsessfully, though I could only created an empty window..
I was wondering how can I write text in the box?
This is my function that creates the dialog box, where ghInstance is the instance of the window :
void CreateDialogBox(HWND hwnd)
{
CreateWindowEx(WS_EX_DLGMODALFRAME | WS_EX_TOPMOST, TEXT("DialogClass"), TEXT("About Us"), WS_VISIBLE | WS_SYSMENU | WS_CAPTION , 100, 100, 200, 150, NULL, NULL, ghInstance, NULL);
}
So how can I write inside that empty window some stuff?
Thanks!
This tutorial, provided by Microsoft (MSDN) themselves should come in handy:
http://msdn.microsoft.com/en-us/library/vstudio/bb384843.aspx
Take note of the WM_PAINT section. That's for drawing simple text.
You can also create controls on the window, for example:
C++ Win32 Multiline static label
If you are using MS VC++, you can try editing the pre-made About us in the resource script. Or you hand craft it in a resource script.
DialogboxName DIALOGEX 0, 0, 170, 62
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About Us"
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
ICON 128,IDC_STATIC,14,14,21,20
LTEXT "Program by you, Version 1.0",IDC_STATIC,42,14,114,8,SS_NOPREFIX
LTEXT "Copyright (C) 2016",IDC_STATIC,42,26,114,8
DEFPUSHBUTTON "OK",IDOK,113,41,50,14,WS_GROUP
END
You can reference Charles Petzold Windows programming book, version 5 of it.

Using Tab to move to another edit control in the main app window

Hello I was reading through some other posts about my issue on SO that haven't been quite answered yet (like this). I have the same problem about now. I have a main window on C/Win32 with many edit controls in the form below. Note that those buttons only work on my Main app window...
hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "1",
WS_GROUP | WS_VISIBLE | ES_NUMBER | ES_RIGHT,
180, 94, 28, 20, hwnd, (HMENU)IDC_ATTRIBUTE_FITNESS, GetModuleHandle(NULL), NULL);
and I would like to move from one to another using the tab key. As you can imagine I can't and I have tried whatever I could.
I have tried using any combination WS_EX_CLIENTEDGE and WS_GROUP but nothing worked. Every time I press Tab key while in one of my edit controls I hear the 'beep' tone from Windows. Anyone can provide insightful information about that or maybe a little tutorial or demonstration online to get hold of it? Thanks in advance.
Give your controls the WS_TABSTOP style and then use IsDialogMessage in your message loop. Also see Raymond Chen's "Using the TAB key to navigate in non-dialogs" article for some more details and for sample code.

Creating a window using CreateWindowEx without an icon

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.

How do you place sub controls inside a group box?

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!

Resources