I am creating a MFC application in which there is a skin library which handles the UI effect of rendering the controls (it gets called in oninitdialog). But, meanwhile, I have also the requirement of displaying an icon on the buttons. For this, I am marking the buttons as ownerdrawn=true, and able to display icon, but in this case, skin effect is not taking place on those buttons whose ownerdrawing is done by me. So, my question is, how do I ensure that a control gets ownedrawn by me, and also by any other library.
Call the default handler for OnPaint to make sure the skinning library has a chance to draw the button, then draw your own content over the top.
void OnPaint()
{
Default();
CClientDC dc(this);
// your painting code goes here
}
You don't need owner-draw to display icons in buttons !
Related
I am currently developing a kind of "WinMerge" clone, and currently I am trying to implement a custom scrollbar which should later represent both compared files as a rectangle in the background each.
This is what it looks like at the startup:
However, after scrolling around a little bit, this is what I end up with:
As you can clearly see, only those parts look correct which I explicitely paint over in my paint routine:
void LocationPane::OnPaint(CDCHandle dc)
{
DefWindowProc();
dc = GetDC();
DrawLocationPaneFigures(dc);
}
This is how my control is configured in my .rc file:
CONTROL "",IDC_LOCATIONPANE,"Static",SS_OWNERDRAW | SS_NOTIFY | WS_BORDER | WS_GROUP,7,21,91,541
As you can see, it is an owner drawn control.
How can I erase the background for this control while repainting it?
A static control with SS_OWNERDRAW style receives a WM_DRAWITEM message when it needs to be redrawn.
So first you need to replace your OnPaint() handler by a handler for WM_DRAWITEM. Instead of calling GetDC() use the device context supplied to you in the DRAWITEMSTRUCT.
To erase the background it's generally best to do it as part of the regular painting code to reduce flickering (by calling FillRect() for instance).
I suggest to always draw the whole client area of your control. Then you may handle WM_ERASEBKGND to return TRUE without calling DefWindowProc() to reduce flickering even more.
Ok, so my intention is to "prettify" a UI I'm working on. I'm familiar with using GDI+ to manually draw my controls but my target today is simply BitBlitting png's on my DC directly.
That works nice and fine with the main frame, a few buttons and perhaps some menus.
My question is - how would you skin something more complicated like a combobox, listview or more "dynamic" controls using such skins?
Thank you. My target platform is Windows and I'm using C++ with the wxWidgets framework.
To 'skin' an existing control you'll have to subclass the window and catch the draw messages.
roughly:
// Subclass the control
WNDPROC lpfnOldCtrlProc;
lpfnOldCtrlProc = (WNDPROC)SetWindowLong(ControlHwnd, GWL_WNDPROC,
(DWORD)WinSubClassFunc );
and in your WinSubClassFunc:
switch( message )
{
case WM_DRAWITEM: // owner-draw the item
However, if you want to fully 'skin' a control e.g. change all elements of a ComboBox (border, entrybox, dropdown button, droplist etc.) then this becomes really messy.
Personally, I find it is easier to create your own control from scratch than try to subclass an existing control which consists of multiple window items.
The above methods works fine for e.g. using a standard combobox with a droplist and subclass it to make it contain a droplist of colour bars.
When exactly is WM_PAINT called? Im trying to create a dialog based slot machine application, but i've run into a couple of logical issues. My application will consist of:
"Spin" Button
Exit Button
Three BMP images to display the results of the spin(coin/heart/soldier)
How will i show the final result of the spin using the BMP images? Am i correct in using WM_PAINT to attempt to display the images, how will i refresh the screen each time the user presses the spin button to show the new images? I really appreciate the help!
Dialog boxes normally use DefDlgProc as the window procedure. You can't handle WM_PAINT in your DialogProc (it isn't a window procedure). You can use your own window procedure with a dialog but that's probably more trouble than it's worth.
The simplest way to display a bitmap on a dialog is to use a static control with the SS_BITMAP style.
You can change the displayed bitmap by sending the STM_SETIMAGE message to the static control. The control will take care of repainting itself with the new bitmap.
This is OK if you just want to display the result of a spin, but won't work very well if you want to animate the spinning of the reels. To handle this you could create your own static control (i.e. a window for each reel) that would display a portion of a reel bitmap.
I inherited an MFC app, and it has a window that has several owner-draw widgets that respond to OnPaint and do various drawing.
I noticed that in order to force the controls to redraw in response to various user actions, there was the following code:
CRect rect;
m_myControl.GetWindowRect(&rect);
ScreenToClient(&rect);
InvalidateRect(&rect, FALSE);
I thought this could be simplified like so:
m_myControl.Invalidate(FALSE);
But, in practice, when I do it this way, the control paints sometimes but not others. Specifically, when I'm interacting with controls in the window, sometimes myControl ends up just painting as solid gray. I changed the code back to the more-complicated InvalidateRect style and it's working great again.
Why would there be a difference here?
When you invalidate a window, you don't invalidate the window underneath it. If the parent window is responsible for drawing the control it won't get triggered because you didn't tell it that it needed updating. The original code does the right thing in that case.
Hello there I have issue with overlapping of child windows,I have created a software with menu driven interface( IDR_MAINFRAME - CFormView
etc) and upon clicking one of the menu items another child-window appears( Dialog based ) where I do the calculations as a normal
calculator.Now if I open any other entry say conversion of metrics which is also in menu entry then on overlapping with any other such
window the background windows gets horribly disfigured and if i move about the calculator or the metrics conversion calculator randomly
they get disfigured and its a mess.Also I have put up a bitmap image on the background.Upon moving the calculator the background image also
gets erased.
Please let me know about how to handle this issue.I have googled and found that handling of paint messages or WM_ERASEBKGND helps ..but I
have tried this piece of code which just doesn't help in OnEraseBkGnd();
BOOL COfficesoftDlg::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
CRect Rect;
GetClientRect(Rect);
//ClientToScreen(&Rect);
//this->ScreenToClient(&Rect);
this->InvalidateRect(Rect);
return CDialog::OnEraseBkgnd(pDC);
}
how can i achieve the smooth overlapping of different windows like a notepad overlapping a word document or even a calculator or even a VC6
IDE in my project.
Please explain it with an example .I am just a newbie and I need to understand in detail...thanks and regards
Override OnEraseBkgnd and return true so it stops erasing the background you're painting. Returning TRUE says that you've done the work. If you simply call the base class implementation, it's going to do this for you, and you'll lose the background until it gets a chance to paint.
You're not getting paint messages to the parent window for some reason. Make sure you're calling the modal in the correct manner. DoModal() works fine. Make sure you're not just creating the modal and showing it.
If your windows are children on the same dialog/window and they overlap or you have children on either dialog/window, make sure that you use clipchildren and clipsiblings (if children on a window overlap). Otherwise they'll get to paint in any order they choose artifacting all over the place.
Ensure that you're painting to memory and bitblting back to your dialog, otherwise you'll get a flashing effect.