• 0

[C++, Win32] Window/Control font & background colour


Question

I'm having problems here, C++ Win32 GUI programming is hard!

Problem #1: When i created the project in visual studio, it gave me some code that produced the main window. The code specifies the background colour for the window class as COLOR_WINDOW+1. However, here on Windows 7, that's white! I'd really like it to be light grey as per the norm. I can get this with COLOR_WINDOW without the '+1'. But i'm worried about the effect of this across other versions of windows and custom themes. Is this the recommended solution, or should I do it a different way?

Problem #2: More importantly, I'm having trouble with fonts! I've created a new window (an actual window, not a dialog), and created a button on it. The font used for the button is a really old system font (bold, black, and blocky). How do I get the window and all of it's controls to take on the default system font (Segoe UI for win7)? I've spent hours on this and haven't come up with an answer yet :(

SYSTEM_FONT and DEFAULT_GUI_FONT are apparently obsolete. I've heard about a SystemParametersInfo() function, NONCLIENTMETRICS sturctures and LOGFONTs. Am I going down the right path with that? How does this help me? Do i want lfMessageFont ("information about the font used in message boxes")????

I'm doing everything the hard way btw. Plain old C++, Win32, no MFC, no "forms", no dialog boxes designed in a resource file, and it's my first gui app using C++.

Please help...

12 answers to this question

Recommended Posts

  • 0

For #1: You "need" the "+1" so if you want to use COLOR_BTNFACE you need to have "COLOR_BTNFACE + 1"

For #2: I'd go along what you were saying with the lfMessageFont, simple call to CreateFontIndirect() will give you the HFONT needed for the WM_SETFONT message.

  • 0

Unfortunately, this is the way of c-based GUI programming. It's a remarkable pain. Pretty soon you'll realize why even commercial software devs are starting to switch to .NET to program the user interface and calling native code for operations that benefit from it.

  • 0

ok, almost there...

problem #1: I've used "COLOR_BTNFACE+1" as suggested.

problem #2:

first, the code, just to help others...

----------------

i'm using the following code to get the font:

HFONT hGlobalFont = NULL;
void GetWndFont()
{
	NONCLIENTMETRICS info;
	info.cbSize = sizeof(info);
	::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);
	hGlobalFont = CreateFontIndirect(&info.lfMessageFont);
}

and then to set the font, for a single control:

SendMessage(hwnd, WM_SETFONT, (WPARAM)hGlobalFont, MAKELPARAM(FALSE, 0));

for all child windows:

EnumChildWindows(parentHwnd, setWndFont, NULL);

//callback function to be used by EnumChildWindow()
BOOL CALLBACK setWndFont(HWND itemHwnd, LPARAM lParam)
{
	SendMessage(itemHwnd, WM_SETFONT, (WPARAM)hGlobalFontt, MAKELPARAM(FALSE, 0));
	return true;
}

----------------

With the above, I've got the correct font applied to all of the window controls. I also sent a message to the window itself, though i'm not certain it had any effect.

There are a couple of little quirks with my window I'd like to solve though:

1) Size discrepancies.

Before attempting to make the window in C++, I designed it as a VB.Net form. I took the unit positions and sizes from the properties of everything in VB and used them in my CreateWindow() statements in C++. Comparing the two windows, they're not quite the same though!...

- The width and height of the C++ window are slightly larger. There's 3mm difference on my screen, and leaves a gap between the controls and the right and bottom borders (all controls seem to line up correctly comparing the two windows). I set the font on the actual window in the VB.Net form to the same as for the controls below. Changing the size of the VB.Net form's font does not increase the size of the form until I get to 8.63pt, and then it is much larger than the C++ form, about 1 inch for height and width. (My screen is 21.5" 1680x1050).

- The original font in the VB form was "Microsoft Sans Serif, 8.25pt". I changed this to "Segoe UI, 8.25pt". The font size is too small though compared to the C++ window. If I increase it to "Segoe UI, 8.26pt" the font to me looks like it matches the C++ form, although it is very hard to tell. 8.26-9pt all seem the same as far as i can tell, the size of the text increases again at 9.1pt. However, even at just 8.26pt the text on a couple of the buttons does not fit and spills over into multiple lines, whereas the same text in what looks to be the same sized font in the C++ buttons, is fine...

Can anyone shed any light on this, and tell me how I can get the design to match the result?

I know I can just alter the unit sizes i'm using, to fix the fundamental issue, but I'd really prefer to tackle the cause!...

2) In *some* of the the corners of *some* of the text boxes, there's a little dark grey dot. Zooming in, they're not all the same shade. Switching window/control focus can change how many of them there are... Maybe it's a Windows 7 bug... But yet the VB.Net form doesn't do this...

Screenshot showing the problems (C++ on the left, VB.Net on the right):

post-51082-1251656129_thumb.png

Edit: Thought. The size of text in child windows seems to be effected by the font of the parent window, when playing around with VB.Net. Could it be that all of the size problems stem from the WM_SETFONT message having no effect what-so-ever on the C++ parent window, and therefore it's basing the size of everything based on aspects of that old system font it was previously using? If so, how do I fix this?

Edited by theblazingangel
  • 0

Win32 GUI programming shouldn't be this difficult because you shouldn't be doing everything using the raw C APIs (BTW, the API is in C, not C++).

There are several ways to do Win32 GUIs:

1) Raw calls to the raw C APIs such as CreateWindow, etc. This is complicated, tedious, and relatively speaking, it's rarely used. It's used only in situations where you need such low-level control over the UI or in situations where it's easier to do it this way.

2) Use the dialog manager. Most of the UI in the Windows operating system itself uses the dialog manager. The dialog manager has been around for a long time (I think been around since Windows 2?), uses a simple C API, and support for it is built into the OS. In fact, Microsoft's UI layout guidelines were written specifically for windows created with the dialog editor (using DPI-independent dialog units) (to adhere to these guidelines using any other method of GUI programming will require that you do conversions).

3) Use MFC. This is a set of C++ wrapper classes for the low-level C APIs. The problem with MFC is that it introduces MFC dependencies. MSFT doesn't use MFC very much.

4) Use a third-party widget layer like wxWindows. Common with open-source projects, it does introduce dependencies, but nothing major.

5) Use various .NET stuff. The problem with .NET is that, well, it's .NET, and you get all the baggage and truckload of dependencies that come with that.

Using the raw API is, as I said, relatively rare, and is usually used on windows with very limited complexity. For example, if you are writing a file manager, you would create the main window using approach #1, which would consist of just a menu bar, a toolbar, a status bar, and a list view--just four UI elements that require very little in the way of positioning or layout. And then all of your other UI--your options dialog, your file information dialog, etc.--would be done using the dialog editor. In fact, if you look at Windows itself, this is how much of the OS is done: low-level CreateWindow is used only for the "main" window with generally limited complexity, and everything else is done with the dialog editor. And if your app just consists of a dialog-like window, then your entire program's UI should be done with the dialog editor (or you could manually write the dialog resource without the editor).

So yes, what you are doing is hard. And complicated. And that's why you're not supposed to do it that way, and that's why even Windows itself doesn't do it that way. I can understand wanting to avoid MFC or .NET (because I, too, avoid them), but the dialog system is really another matter. The dialog manager is built into the OS itself, as a part of user32.dll. And just like CreateWindow and the other low-level stuff, you work with the dialog manager using a C API.

Edited by code.kliu.org
  • 0

A few extra notes:

1) Don't compare a .NET form with a native form. Many .NET controls are not rendered natively, but instead, through a series of manual calls to uxtheme or are self-drawn in a way to emulate native controls. You can tell the difference by noting the lack of a hover fade animation on buttons in themed mode, or in classic mode, the (erroneous and incorrect) failure of .NET controls to respect the 3D light color setting. I don't know what other rendering differences there are, since I rarely touch .NET, but it should be noted that they are not directly comparable. You should be comparing what you get with what you create using the dialog editor, which is native.

2) Pay close attention to the documentation regarding LOGFONT. Namely, how font sizes are natively represented and handled and how that differs from the point size that you specify; this should explain some of the font-size-related questions that you had.

3) I'm not sure about the gray dots. Do you see them with a dialog-editor window?

Edited by code.kliu.org
  • 0

This is mostly just a learning exercise, which is why I'm doing it this way. I'd certainly consider other options for future projects.

I'm not using MFC partly to learn how to do it without first, but also because I'm using the express edition of VC which doesn't have MFC!

I'm avoiding dialogs, again partly to learn how to do it without, but also because the express edition of VC doesn't have the resource file editor that the full version has, and I'm affraid of forgetting to backup the .rc file and VC erasing all my hard work.

In regard to the problems in my last post. I've fixed the grey dot problem! The controls were within a groupbox and I had set the groupbox as their parent window. I just discovered today that groupboxes don't pass messages from controls up to their parent window. I'm now using a RECT for easy positioning of controls, and no longer using the groupboxes themselves as parent windows to the controls they contain. This magically solved the mysterious grey dot problem!

As for the size problem, I've taken onboard what you said about .Net forms, and I'll forget trying to precisely match the C++ form to it.

thanks.

  • 0
  code.kliu.org said:
Win32 GUI programming shouldn't be this difficult because you shouldn't be doing everything using the raw C APIs (BTW, the API is in C, not C++).

1) Raw calls to the raw C APIs such as CreateWindow, etc. This is complicated, tedious, and relatively speaking, it's rarely used.

2) Use the dialog manager. Most of the UI in the Windows operating system itself uses the dialog manager.

It's total BS.

CreateWindow() is used everywhere inside Windows source code !!! (that apparently you never studied..)

You even don't know what is "Dialog manager" : it's a kernel part which manages Dialog Boxes (off topic !)

I make GUI with CreateWindow() and all native, common and avanced controls for nearly 20 years. It's just unbeatable and the best way to manage and understand everything.

  • 0
  Patrick333 said:
CreateWindow() is used everywhere inside Windows source code !!!

Define "everywhere". Your claims are, of course, patently false by the strict definition of "everywhere". But even with a loose definition of "in most situations", you are still wrong. Just poke around Explorer (shell32.dll and explorer.exe) or mspaint.exe. Tell me, how many dialog resources do you see? And now, tell me, how many calls to CreateWindowEx do you count? My disassembler counts 6 calls to CWEx in shell32.dll (3 in explorer.exe) in 5.1.2600. And I see a list of dialog resources so long that they overflow my screen. So, shall we discuss this definition of "everywhere"...?

Yes, I know what the dialog manager is, and yes, it is managing dialog boxes. Which is what we're talking about: UIs that take the form and style of dialog boxes (i.e., most of the UI in Windows, in terms of sheer quantity, and, more to the point, what the OP was trying to implement) should be implemented using the various dlg functions. Of course, as you can attest, this is not a requirement, and if someone feels so inclined to manually create every button, every text box, etc., they can. But it's also not a requirement that people use C; you are certainly free to write your program using x86 assembly if you wanted, but that doesn't mean that it's a particularly good idea.

And no, strictly speaking, it's not a part of the kernel. It's a part of the user subsystem. And not only that, it's implemented using the lower level calls such as CWEx, and it is implemented as more or less a wrapper around these various calls (and there has been much discussion elsewhere about just how the dialog "manager" works, how it is implemented, and how one might write their own dialog "manager" if they are not quite satisfied with what Windows has).

  • 0

Saying that dialogs are "most used" is a bit misleading. Programs tend to only have one main UI, but dozens of popup dialogs. If you look at Explorer (the desktop and file browser), what you are seeing is not a dialog. The same holds true for most programs (although you will occasionally find people having child dialogs in a window).

And for the pedants, Windows today technically only has one subsystem, Win32. Windowing (user) is part of that, although most of the functionality runs in a kernel-mode driver rather than in the subsystem process (which doesn't do much these days) itself. Completely irrelevant to anything though.

  • 0
  code.kliu.org said:
A few extra notes:

1) Don't compare a .NET form with a native form. Many .NET controls are not rendered natively, but instead, through a series of manual calls to uxtheme or are self-drawn in a way to emulate native controls.

Interesting. I know it isn't really related to this thread but I always wondered why there were sometimes inconsistencies. Thanks for the info.

  • 0
  hdood said:
Saying that dialogs are "most used" is a bit misleading. Programs tend to only have one main UI, but dozens of popup dialogs. If you look at Explorer (the desktop and file browser), what you are seeing is not a dialog. The same holds true for most programs (although you will occasionally find people having child dialogs in a window).

Yes, that is true, which is why I did specify in the first post that the "main" UI is usually manually created (because, except for tools and utilities, the "main" UI of an application usually does not take the form of a dialog), and this is also why I qualified my later post with "in terms of sheer quantity".

And yea, subsystem probably wasn't the best word. Component, perhaps? The distinction that I was trying to make was that it's code that exists in a layer above what one normally associates with the "kernel" (with respect to the hierarchy of dependencies).

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Posts

    • This super-powerful GaN charger with four ports is 50% off by Taras Buria Some time ago, I reviewed the Cuktech 10, a powerful 100W GaN charger with three ports. It left positive impressions, and since then, it has served me as my primary charger for my phone, watch, laptop, and tablet. Recently, Cuktech offered me the opportunity to take a look at the model 15, a more powerful 140W GaN charger, this time, with four ports. Right now, this powerful charger is available with a massive discount at just $50.99 (with coupon applied). The Cuktech 15 is the same as the Cuktech 10, just slightly bigger, more powerful, and with one extra port. It has a light metallic finish, but overall, it retains the brand's identity and features. The four ports are well spaced out, and the black plastic insert with a cyan rim has a ribbed texture for better grips. Although I live in Europe, Cuktech sent me a US variant with a retractable plug. Okay, I guess. The ability to retract the plug makes it extra portable, which is nice. A high-power 240W five-foot cable is also included. The charger measures 3.11 x 2.56 x 1.26 inches and weighs 0.737 lbs. The Cuktech 15 has four ports: two high-power Type-C ports, one Type-C port with a lower output, and one Type-A port. The first two Type-C ports can deliver a full 140W in single-port mode (PD 3.1 supported), which is nice—no asterisk or caveats here with combined power or something. If you need the full 140W for one device, you get it. Ports are capable of working in the following modes: Single-port Type-C1 / C2: 140W max 5V 2A, 5V 3A, 9V 3A, 11V 6.1A, 12V 3A, 15V 3A, 20V 5A, 28V 5A Type-C3: 33W max 5V 2A, 5V 2.4A, 9V 2A, 12V 1.5A, 11V 3A Type-A: 18W max 5V 2A, 5V 3A, 9V 2A, 12V 1.5A Multi-Port Type-C1 + C2: 100W + 33W or 65W + 65W Type-C1/C2 + Type-C3: 100W + 33W Type-C1/C2 + Type-A: 100W + 18W Type-C1 + Type-C2 + Type-C3: 65W + 60W + 7.5W or 45W + 45W + 18W Type-C1 + Type-C2 + Type-C3 + Type-A: 65W + 60W + 7.5W As you can see, the charger is pretty robust, and it can power two pretty powerful laptops at once and even have enough oomph to charge a smartphone, albeit at a lower power. Another thing worth mentioning is that the Cuktech 15 delivers "clean" power with pretty low pulsations at about 25-50 mV. The rule of thumb is that the lower the pulsations, the better the charger is for your device's battery health. In this area, Cuktech's charger does not disappoint, and they deliver way better results than 100 mV, which is considered a standard for a good charger. Cuktech uses gallium nitride technology, which enables smaller, more powerful and efficient charging. Speaking of efficiency, the charger is rated for 78% average or 64% at a 10% load. When charging at 120W, I received an average of 80-85%, which is good. Of course, when charging at peak power, it gets hot, but not too much. The Cuktech 15 140W usually costs $99.99, which is undoubtedly not cheap. However, right now, you can get it for half the price, which is a very good deal, considering you get a high-quality charger with plenty of ports and very high power output. Like with the Cuktech 10, you cannot go wrong with this one. CUKTECH 15 140W four-port GaN charger - $50.99 | 30% off + a 20% off coupon As an Amazon Associate, we earn from qualifying purchases.
    • Awesome book, just hope they don't screw up Rocky and the story
    • KDE's KClock is getting Wayland Picture-In-Picture support by David Uzondu The KClock app for KDE Plasma over the years has received a number of updates, like better integration with KRunner and a dedicated background service (kclockd) for managing alarms. Now, it looks like KDE devs want to add something cool: pop-out timers using the new Picture-in-Picture protocol for Wayland. Image: Kai Uwe Broulik This all started from a simple observation. Kai Uwe Broulik, a KDE developer, saw someone using a small timer window during a presentation and thought it was a good idea. The problem is that achieving this kind of "always on top" behavior is handled differently between the old X11 display server and the newer Wayland. With X11, an application could pretty much do whatever it wanted. If a program wanted to draw a drop-down menu, it would just create a borderless window, place it in a specific spot, and grab all user input. Wayland operates on a different philosophy. As Broulik notes, under Wayland, the application describes what it wants, and the compositor gets to decide how to handle it. A drop-down menu is an XDG Popup. The application tells the compositor which button spawned it, and the compositor handles the placement and behavior. This is much more secure and consistent. It also means an application cannot just decide to keep its window on top of everything else. This restriction prevents a web browser from implementing an overlay video player under Wayland. To get around this in a standardized way, a proper Wayland support model for Picture-in-Picture, or PiP, was needed. Enter the xx-pip-v1 protocol. It is a new protocol designed specifically for creating floating PiP windows, and KWin, Plasma's compositor, recently gained support for it. Because it is an experimental protocol, its use is gated behind an environment variable, KWIN_WAYLAND_SUPPORT_XX_PIP_V1. A new protocol is fine for demos, but it needs a real application to find its weaknesses. So Broulik implemented it in KClock. This work allows KClock to offer pop-out timers and even a pop-out stopwatch in a small PiP window. The user could get system-wide options to control where the PiP window appears, or if it appears at all, and have that setting apply to every single application that uses the protocol. You can check out the merge request on GitLab for more technical details about this feature.
    • Nothing of course; it is just a classic syndrome of MAGA pathology.
    • They use it to assessment's in the UK already. Have a friend who said they basically feed response's and prompt during assessment's for many mental health conditions now (essentially tick boxes these days enough ticks and you got it) the AI can prompt questions to ask if its unsure how to score something. It's really good at recognising fractures and broken bones also.
  • Recent Achievements

    • One Month Later
      CHUNWEI earned a badge
      One Month Later
    • Week One Done
      TIGOSS earned a badge
      Week One Done
    • First Post
      henryj earned a badge
      First Post
    • First Post
      CarolynHelen earned a badge
      First Post
    • Reacting Well
      henryj earned a badge
      Reacting Well
  • Popular Contributors

    1. 1
      +primortal
      477
    2. 2
      +FloatingFatMan
      196
    3. 3
      ATLien_0
      164
    4. 4
      Xenon
      81
    5. 5
      Som
      77
  • Tell a friend

    Love Neowin? Tell a friend!