I am developing a GUI application using Embarcadero VCL c++ IDE for windows OS. As part of this project, I have to change color of button with respect to an external state.
I understood that windows32 API will not allow to change the color of button.
Could you please suggest me, how to change button color?
Do you wish to change the background-colour of the button, or the text-colour of it?
Since windows has used visual themes for some time now, if you have commctrl loaded and include a manifest file, the button will be drawn using the default (current) theme.
Options I can see include (a) custom-drawing the background (b) changing the text-colour in the normal draw process (c) drawing the button without a theme (i.e drawing a 'flat' button).
You could simply draw a bitmap-button, changing the bitmap depending on the state of the button. You could also use a single bitmap, tinting it using the HSL or HSV colour-space, depending on the state.
As for the flat type of button, I think you can probably change it's background-colour in much the same way as you can change the colour of the text - by intervening during the standard draw process and changing the colour from 3D_FACE (or whatever it is, I forget) to whatever you'd like.
If you look at the calculator included with windows XP, you can see an example of changing the text colour.
CodeProject.com likely has a stack of articles that would help in this endeavour. :)
Related
I have a Qt app that runs on macOS. I found a way to change the color of the titlebar here, however I want to take it a step further. I want to mimic the titlebar that the Slack and Discord apps use. For example:
As you can see, the color of the controls in the window extend to the very top of the app's window. I figure there are two ways to accomplish what I want:
I can build on the code pasted above. Looking through some of the Apple developer documentation, I think I can create a couple NsWindows on top of the titlebar with whatever width I want and attach the titlebar as a parent for those windows. Once I do that I should be able to make the same backgroundColor() color call for each one. Of course, this will require me to keep track of when the controls or window are resized and adjust the NsWindows of the titlebar, and I am not sure what (if any) issues that could cause.
Maybe there is a way to essentially set the height of the titlebar to 0? I wonder if that's what the Discord app is doing because:
if you look closely, the edit box that says "Find or start a conversation" is vertically lined with the close, minimize and maximize buttons, as is the "Activity" label. But if the controls do extend to the top of the app's window then how are the standard app buttons getting painted?
I'd be curious to know how Slack and Discord accomplish this even though I know they're not using Qt.
I realize there is not a Qt solution since Qt does not paint the titlebar. I know this will be OS-specific, but since I do not have any real experience with Objective-C++ or working with Cocoa (all of my programming experience on macOS has been standard C++ with non-UI or Qt-based code) I'd appreciate any suggestions or guidance!
Natively this is done with fullSizeContentView and titlebarAppearsTransparent properties of NSWindow. Once you set them to true, you can draw or place controls beneath the title bar.
I made an MFC app for my friend using VS2015 in Win10. It looks like this, which is exactly the same as in resource editor.
.
But when he ran the app on his computer in Win7, the Bitmap image in Picture Control enlarges and covers up some text boxes below, which looks like this.
.
After I searched and realized it may be related with DPI awareness. I disabled DPI-Awareness in property page of Manifest Tool and rebuilt. The same thing happened even when it runs in Win10.
Could someone help me explain the cause of this and find a solution to fix the size of the image control? Thanks.
The main problem is that a dialog from a resource is always measured in DLUs.
And DLUs are calculated from the size of the font, that is used for the dialog.
See this article how dialog base units are calculated.
Now you have a static picture control that is sized in DLUs. The bitmap is just scaled in pixels and is never resized, when you assign it to a static dialog control. And because the real size of the static control depends on the used font, you get different layouts for your dialog and your bitmap.
And because just the font changes when you choose no DPI awareness and because the font changes from windows version to windows version your dialog always look different.
Advice: Paint you picture your own and stretch it accordingly.
Also this stackoverflow question is nice documents and shows the effect of DLUs.
And here some code for auto sizeing picture controls.
An auto-sizing bitmap picture control
A simple image preview class using GDI+
CxImage
Normally, I prefer to keep control in my hand by using SetWindowPos() to set the size of image I want in different situations. You can use below two lines to control/set position and size of your image.
Assume ID of the Picture Control is IDC_STATIC2 then you can use like:
CStatic * pStatic = (CStatic *) GetDlgItem(IDC_STATIC2);
pStatic->SetWindowPos(NULL,20,20,50,50,0);
I am updating a GUI of a Win32 Application in white text on black background. Thats simple for my content. But how can i change also the color of my child windows (Titlebar, Scrollbar etc.). i Know there is WM_CTLCOLORDLG to set the color of Dialogs. I also know there is WM_NCPAINT, but that would leave all painting (i.e of Scrollbars) to me. All i want, is to set colors of my choice.
You can use SetSysColors() to change the colour for window captions, borders, etc. (see http://msdn.microsoft.com/en-us/library/ms724940(VS.85).aspx). However this will change the colour for all windows, not just yours, so it is at the least an unfriendly thing to do.
One option is to use SetSysColors() to change the active window caption colour when your application has focus and to reset it to the defaults when it loses focus. But I'd say that's klunky and not really in keeping with good practice (suppose your application crashes? and there might be some flickering).
WM_NCPAINT is there so that you can do things like this. It is a bit of a pain, but maybe that's to discourage you from creating non-standard windows... ;-)
Hook GetSysColor() (Using something like Microsoft Detours)
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.
I'm trying to implement some drag and drop functionality for a material system being developed at my work. Part of this system includes a 'Material Library' which acts as a repository, divided into groups, of saved materials on the user's hard drive.
As part of some UI polish, I was hoping to implement a 'highlight' type feature. When dragging and dropping, windows that you can legally drop a material onto will very subtly change color to improve feedback to the user that this is a valid action.
I am changing the bar with 'Basic Materials' (Just a CWnd with a CStatic) from having a medium gray background when unhighlighed to a blue background when hovered over. It all works well, the OnDragEnter and OnDragExit messages seem robust and set a flag indicating the highlight status. Then in OnCtrlColor I do this:
if (!m_bHighlighted) {
pDC->FillSolidRect(0, 0, m_SizeX, kGroupHeaderHeight, kBackgroundColour);
}
else {
pDC->FillSolidRect(0, 0, m_SizeX, kGroupHeaderHeight, kHighlightedBackgroundColour);
}
However, as you can see in the screenshot, the painting 'glitches' below the dragged object, leaving the original gray in place. It looks really ugly and basically spoils the whole effect.
Is there any way I can get around this?
Remote debugging is a godsend for debugging visual issues. It's a pain to set up, but having a VM ready for remote debugging will pay off for sure.
What I like to do is set a ton of breakpoints in my paint handling, as well as in the framework paint code itself. This allows you to effectively "freeze frame" the painting without borking it up by flipping into devenv. This way you can get the true picture of who's painting in what order, and where you've got the chance to break in a fill that rect the way you need to.
It almost looks like the CStatic doesn't know that it needs to repaint itself, so the background color of the draggable object is left behind. Maybe try to invalidate the CStatic, and see if that helps at all?
Thanks for the answers guys, ajryan, you seem to always come up with help for my questions so extra thanks.
Thankfully this time the answer was fairly straightforward....
ImageList_DragShowNolock(FALSE);
m_pDragDropTargetWnd->SendMessage(WM_USER_DRAG_DROP_OBJECT_DRAG_ENTER, (WPARAM)pDragDropObject, (LPARAM)(&dragDropPoint));
ImageList_DragShowNolock(TRUE);
This turns off the drawing of the dragged image, then sends a message to the window being entered to repaint in a highlighted state, then finally redraws the drag image over the top. Seems to have done the trick.