Visual Studio's windows have a close button (as well as other frame controls) that blend into the caption color and appear like so:
I was wondering if there's an accepted way of drawing controls like that. Do controls like these use DrawFrameControl or DrawThemeBackground, or do they use another approach altogether?
Thank you for any information.
There are two approaches for creating custom buttons using Win32 API:
1. Draw the control yourself. This is very complicated and requires a lot of knowledge about Win32 controls. Here are some links to get you started:
https://learn.microsoft.com/en-us/windows/win32/controls/user-controls-intro
https://www.codeproject.com/Articles/646482/Custom-Controls-in-Win-API-Control-Customization
Owner-drawn button, WM_CTLCOLORBTN and WM_DRAWITEM (clearing an HDC)
2. Modify an existing control using SubclassWindow. This is much easier, but in most cases very limited.
For example you can use a static control and handle mouse activity for it. You can also use multiple controls and show and move them as needed.
There is no set way of doing this since it's custom logic. But here are some links:
https://learn.microsoft.com/en-us/windows/win32/controls/window-controls
https://learn.microsoft.com/en-us/windows/win32/inputdev/mouse-input
https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-mousemove
Related
I've been looking around for awhile about how to produce buttons using Direct2D and DirectWrite with no luck. I'm comfortable with shapes, text and that jazz. However, it suddenly occurred to me I might be looking about it in the wrong way.
Take the sentence:
you draw your controls and content for your app using the Direct2D and
DirectWrite APIs, handling all the input events directly.
I'm now thinking this means that instead of being able to quickly produce a fully functional button as I would using XAML. I would draw the button, manually check the location of the mouse on click, whether it's within the button boundaries and then handle the event? Similar method for hovering without the click.
Is this the kind of method required when using Direct2D and DirectWrite?
I haven't any experience with DirectX, but in OpenGL I build my buttons from scratch. Assuming you have animated sprites implemented, your buttons are essentially sprites that play certain animations in response to being clicked, hovered over, etc., and which you can register callbacks with. In my 2D engine, I have a class called UiButton, which inherits Sprite, and listens for various UI events. It gets more complicated when you want to handle keyboard navigation (arrow keys + enter to select) as you have to think about how the buttons are connected and which of them has focus at any given moment.
Here is my implementation for reference:
Headers: https://github.com/RobJinman/dodge/tree/master/Dodge/include/dodge/ui
Source: https://github.com/RobJinman/dodge/tree/master/Dodge/src/ui
If you're not prepared to roll your own, Googling "direct2d gui framework" seems to bring up some promising results.
Sorry I can't be of more help.
Yes, to draw a UI Button with Direct2D, you need to handle everything yourself, why? Direct2D is a 2D graphics API, not controls library. you need to draw the layout of your button, and handle the message of your button(such as click, mouse hover...), you lost lots of convenient and that's time-consuming, but the most important thing is: you can control it by yourself!
Direct2D is a graphics library. UI controls like, Text-selection, Textbox, and Buttons is not a part of it. However the benefits of using Direct2D and DirectWrite is we can implement our own UI controls, and having a full control of it.
Please also see: ID2D1Geometry::FillsContainsPoint() for hit-testing task.
I have a general question on how to develop an image viewer plugin with Firebreath. For that, I would like to incorporate a GUI framework, like wxwidget or Qt. The GUI would be used to to fire up some dialogs, adding a toolbar on top, or to open context menus with right clicking an image.
As far as I understand I have a hwnd handle and so I can draw onto a window. I also understand that I have various events I can react on, like mouse button clicks or keyboard strokes. But it fails me how I would add graphical menus, buttons, etc. I know I could use html around the window but that's not the route I like to take.
For instance, does it makes sense to render an user interface offline (in memory) onto an image and then keep somehow track of the state internally?
Has anyone done such thing? Or can anyone give me some insight on how to accomplish adding a user interface.
Assuming you only care about windows and assuming that you don't mind using a windowed plugin, which is the easiest (but no HTML elements can float over the plugin), it should be no different than creating a GUI in any other windows application.
You are given a window that shows up with the AttachedEvent; when DetachedEvent is fired you need to stop using the window. Many people create a child window inside that parent window and use that for all their actual real code which makes it a little easier to use one of those other abstractions, but that's basically all there is to it. I don't know specifically how you'd do it with QT or wxwidget but you'd create a child window of that HWND that you are given and have the abstraction do your thing for you.
As to whether or not it would be rendering things offscreen, etc, I have no idea; that would totally depend on the window system. There is no reason that I know of that you would need to do that, and most things just draw directly to the HWND, but there are a zillion different ways you could do it. It looks to me like what you really need is to understand how drawing in Windows actually works.
I hope that helps
Main aim is wanting to draw Tab's within the draw area of the Toolbar of the Applicaiton for a NoteBook or Tab's to use the above space instead of being bellow the toolbar.
The frame work we're using is WxWidgets, C++/C. I have looked around but have not been able to find a solution or if anyone has done a similar approach with drawing tab's actually inside the toolbar itself.
I read some Microsoft MSDN articles and they recommend against controls drawing over controls.
I did some test's today, and think I've come up with a solution. My solution is to draw the window like normal, but have the NoteBook on the right in a child window that is dynamically resized and repositioned so that it's tab's are overlay on-top of the toolbar to make the most effective use of the area. I would have to deal with on focus and lose focus window messages, but this is the most elegant way I can think about achieving the task.
Any Idea's you can recommend or problem's I may face with following this approach.
I would be concerned about using overlapping widgets like this. Although it may not look quite the same visually I would suggest looking at wxToolBook which puts tabs in a toolbar and would solve your problem, you could use the GetToolBar method to insert your own toolbar items.
If that wasn't close enough visually to what you are looking to achieve I would suggest deriving a new control from wxBookCtrlBase and then creating a tab control with custom drawn tabs which you could add to the toolbar using wxToolBar::AddControl.
I have implemented my custom button inheriting from CButton and drawing it by using uxtheme.dll (DrawThemeBackground with BP_PUSHBUTTON).
Everything works fine but I have two statuses (Normal and Pressed) which Hot status is the same. It means when the user places the cursor over the button it is drawn alike regardless the button status (Pressed or not).
This is a bit confusing to the user and I would like to change the way the button is drawn in Pressed & Hot status. Does anybody know a way?
I have also thought about custumizing the whole drawing but the buttons use gradients, borders, shadows, etc. So it is not easy to achive the same look&feel drawing everything by myself. Is there a way to find the source code of the dll or know how to do it?
Thanks in advance.
Javier
Note: I think I could be able to achive what I want to do by using CMFCButton and overriding the OnDraw method. Let the control draw the button on OnDrawBorder and then drawing the inside button myself. But I need to know how the control draws the inside button when pressed. It is a gradient and I can't guess how it's done. Does anybody have a clue?
In answer to your second question, if you derive from CMFCButton instead of CButton you can override OnDraw() or OnDrawText() instead of the usual DrawItem(). That way the default button background will be drawn, and then your drawing code is executed.
The only way I know of to really tackle this is to use 'custom draw', rather than 'owner draw'. Custom draw came in with Windows 2000, but is only used by button controls with comctrl32 6.0 (so Windows XP onwards), isn't very clearly documented, and isn't something MFC goes out of its way to support.
Anyway, the good thing about custom draw is that it lets you hook in at various points in the drawing process, unlike owner draw, which makes you deal with the whole thing. Have a look in MSDN at the NM_CUSTOMDRAW notification message.
For the other part of your problem, detecting the 'hot' state, the easiest way to do this is to use WM_MOUSEMOVE messages and the TrackMouseEvent() function to track whether the mouse is over your button.
Unfortunately this is a bit of a vague answer: the amount of code you need to demonstrate a button that uses custom draw is a bit too much to type into these answer boxes! I do have a project that demonstrates such techniques, using a custom draw button (falling back to owner draw on older Windows versions) that adds a little arrow to the button. You can have a look at the source code by getting
Windows_UI_source.zip
Open it and have a look at the "DropArrowButton" class. The important bit is the OnCustomDraw() handler and its helper function DrawControl(): these get called at the various button drawing phases, and use UxTheme to draw the control appropriately.
I finally figured out how to achive what I want to do. It's pretty easy indeed.
I use two calls to DrawThemeBackground. The first one with PBS_PRESSED and the second one with state PBS_HOT. Then I make a ExcludeClipRect to avoid from drawing over the center of the button.
Something like this:
DrawThemeBackground( hTheme,
pCustomDraw->hdc,
BP_PUSHBUTTON,
PBS_PRESSED,
&pCustomDraw->rc,
NULL);
CDC *pDC = CDC::FromHandle(pCustomDraw->hdc);
CRect rectClient;
GetClientRect(rectClient);
CRect rectInternal = rectClient;
rectInternal.DeflateRect(4,4);
pDC->SelectClipRgn(NULL);
pDC->ExcludeClipRect(&rectInternal);
DrawThemeBackground( hTheme,
pCustomDraw->hdc,
BP_PUSHBUTTON,
PBS_HOT,
&pCustomDraw->rc,
NULL);
pDC->SelectClipRgn(NULL);
Of course this is not the whole code but I think is enough to make my point.
Thanks.
How Would I go about placing text on the windows desktop? I've been told that GetDesktopWindow() is what I need but I need an example.
I'm assuming your ultimate goal is displaying some sort of status information on the desktop.
You will have to do either:
Inject a DLL into Explorer's process and subclass the desktop window (the SysListView32 at the bottom of the Progman window's hierarchy) to paint your text directly onto it.
Create a nonactivatable window whose background is painted using PaintDesktop and paint your text on it.
First solution is the most intrusive, and quite hard to code, so I would not recommend it.
Second solution allows the most flexibility. No "undocumented" or reliance on a specific implementation of Explorer, or even of just having Explorer as a shell.
In order to prevent a window from being brought to the top when clicked, you can use the extended window style WS_EX_NOACTIVATE on Windows 2000 and up. On downlevel systems, you can handle the WM_MOUSEACTIVATE message and return MA_NOACTIVATE.
You can get away with the PaintDesktop call if you need true transparency by using layered windows, but the concept stays the same. I wrote another answer detailing how to properly do layered windows with alpha using GDI+.
Why not just draw the text in the desktop wallpaper image file?
This solution would be feasible if you don't have to update the information too often and if you have a wallpaper image.
One can easily use CImage class to load the wallpaper image, CImage::GetDC() to obtain a device context to draw into, then save the new image, and finally update the desktop wallpaper to the new image.
i haven't tried but i assume you could do the following:
use GetDesktopWindow to retrieve the handle of the desktop window
use SetWindowLong to point the windows message handler to your own procedure
in your proc, process the WM_PAINT message (or whatever) and draw what you need.
in your proc, call the original message handler (as returned by SetWindowLong).
not 100% sure it will work, but seems like it should as this is the normal way to subclass a window.
-don
If your intent is to produce something like the Sidebar, you probably just want to create one or more layered windows. That will also allow you to process mouse clicks and other normal sources of input, and if you supply the alpha channel information, Windows will make sure that your window is drawn properly at all times. If you don't want the window to be interactive, use appropriate styles (such as WS_EX_NOACTIVATE) like Koro suggests.