How to Ownerdraw a Windows Frame?

Just starting out? Need help? Post your questions and find answers here.
Konne
Enthusiast
Enthusiast
Posts: 434
Joined: Thu May 12, 2005 9:15 pm

How to Ownerdraw a Windows Frame?

Post by Konne »

Hello, I just don't get it. How do I need to use #WM_NCPAINT, so that I can draw the Window Frame by my own. (There shouldn't be flickering at all) Could someone make a very easy example so that I would understand it?

Hope someone can help me.

Thx
Apart from that Mrs Lincoln, how was the show?
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8452
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

I'm not sure I understand exactly what you're trying to accomplish, but there are several approaches to ownerdrawing a window frame/background. Here is an example of one of the easier ways, just to get a dialog started and hopefully inspire some more responses with alternatives:

Code: Select all

CreateImage(0,640,480,32) 
captionfont = FontID(LoadFont(#PB_Any,"Tahoma",10,#PB_Font_Bold))
hDC=StartDrawing(ImageOutput(0)) 
  Box(0,0,640,480,#White) 
  Box(0,0,640,25,#Blue) 
  DrawIconEx_(hDC,7,6,LoadIcon_(0,#IDI_ASTERISK),16,16,0,0,#DI_NORMAL|#DI_COMPAT)
  DrawingFont(captionfont)
  DrawText(32,5,"I can draw my own window!",#White,#Blue)
  DrawingMode(#PB_2DDrawing_Outlined) 
  Box(0,0,640,480,#Black) 
StopDrawing() 

Global hBrush = CreatePatternBrush_(ImageID(0)) 

OpenWindow(0,0,0,640,480,"",#PB_Window_ScreenCentered|#PB_Window_BorderLess) 
CreateGadgetList(WindowID(0)) 
ButtonGadget(0,617,3,20,20,"X") 
SetGadgetFont(0,captionfont)

SetClassLong_(WindowID(0),#GCL_HBRBACKGROUND, hBrush) 
InvalidateRect_(WindowID(0),0,1) 

Repeat 
  EventID = WaitWindowEvent() 
  Select EventID 
    Case #WM_LBUTTONDOWN 
      If WindowMouseY(0)<=25 
        SendMessage_(WindowID(0),#WM_NCLBUTTONDOWN,#HTCAPTION,0) 
      EndIf 
  EndSelect 
Until EventID = #PB_Event_Gadget And EventGadget() = 0 

DeleteObject_(hBrush) 
Last edited by netmaestro on Thu Mar 08, 2007 12:59 am, edited 1 time in total.
BERESHEIT
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Post by Joakim Christiansen »

I also want to draw a custom border but I need the window menu to be inside it, any ideas?
I like logic, hence I dislike humans but love computers.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8452
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

Here's an alternate way you can draw the window frame by responding to WM_NCPAINT:

Code: Select all

Global frame ; Frame region is persistent 

Procedure WNDPROC(hwnd, msg, wparam, lparam) 
  result = #PB_ProcessPureBasicEvents 
  
  Select msg 
    Case #WM_NCPAINT 
      hdc = GetWindowDC_(hwnd) 
      hbr=CreateSolidBrush_(#Green) 
      SelectObject_(hdc, hbr) 
      PaintRgn_(hdc,frame) 
      DrawIconEx_(hDC,7,7,LoadIcon_(0,#IDI_ASTERISK),18,18,0,0,#DI_NORMAL|#DI_COMPAT) 
      SetBkMode_(hdc, #TRANSPARENT) 
      SetTextColor_(hdc,#Yellow) 
      TextOut_(hdc, 32,7, @"I can draw my own window frame!", 31) 
      ReleaseDC_(hwnd, hdc) 
      DeleteObject_(hbr) 
      result = 0 
    Case #WM_ACTIVATEAPP,#WM_MOUSEACTIVATE, #WM_PAINT, #WM_GETICON, #WM_GETTEXT, #WM_NCACTIVATE, #WM_SYSCOMMAND, #WM_SETFOCUS 
      RedrawWindow_(WindowID(0), 0, frame, #RDW_INVALIDATE|#RDW_FRAME) 
  EndSelect 

  ProcedureReturn result 
  
EndProcedure 

OpenWindow(0,0,0,320,240,"",#PB_Window_ScreenCentered) 

; Create region for frame area only to be updated in WNDPROC 
GetWindowRect_(WindowID(0),@wr.RECT)
ww=wr\right-wr\left
hh=wr\bottom-wr\top
x = GetSystemMetrics_(#SM_CXFRAME)
y = GetSystemMetrics_(#SM_CYCAPTION)+GetSystemMetrics_(#SM_CYFRAME)
cright = ww-GetSystemMetrics_(#SM_CXFRAME)
cbottom = hh-GetSystemMetrics_(#SM_CYFRAME)
whole = CreateRectRgn_(0,0,ww,hh) 
frame = CreateRectRgn_(0,0,ww,hh) 
client = CreateRectRgn_(x,y,cright,cbottom) 
CombineRgn_(frame,whole,client,#RGN_XOR) 
DeleteObject_(whole) 
DeleteObject_(client) 

SetWindowCallback(@WNDPROC()) 
CreateGadgetList(WindowID(0)) 
ButtonGadget(0,WindowWidth(0)/2-30,WindowHeight(0)-30,60,20,"Close") 

Repeat 
  ev=WaitWindowEvent() 
Until ev=#PB_Event_Gadget And EventGadget() = 0 

DeleteObject_(frame) 
BERESHEIT
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Nice one. :)
I may look like a mule, but I'm not a complete ass.
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Post by Joakim Christiansen »

Sweet, but if you add a menu to it on Vista it fucks up a little :P
But I think I should be able to fix it so thanks!
I like logic, hence I dislike humans but love computers.
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Post by Joakim Christiansen »

Code: Select all

      DrawIconEx_(hDC,5,3,LoadIcon_(0,#IDI_QUESTION),18,18,0,0,#DI_NORMAL|#DI_COMPAT) 
      SetBkMode_(hdc, #TRANSPARENT)
      SetTextColor_(hdc,#White)
      TextOut_(hdc, 32,4, @"I can draw my own window frame!", 31)

Code: Select all

x = GetSystemMetrics_(#SM_CXFRAME)-5
y = GetSystemMetrics_(#SM_CYCAPTION)+GetSystemMetrics_(#SM_CYFRAME)-5
cright = ww-GetSystemMetrics_(#SM_CXFRAME)+5
cbottom = hh-GetSystemMetrics_(#SM_CYFRAME)+5

Code: Select all

ButtonGadget(0,WindowWidth(0)/2-30,WindowHeight(0)-60,60,20,"Close")
Just did these changes and it works fine with and without a menu, but I haven't tested on XP yet.
I like logic, hence I dislike humans but love computers.
dell_jockey
Enthusiast
Enthusiast
Posts: 767
Joined: Sat Jan 24, 2004 6:56 pm

Post by dell_jockey »

Joakim,

it works on XP, with minor alignment problems on the right side of the header bar.
cheers,
dell_jockey
________
http://blog.forex-trading-ideas.com
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8452
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

It's just a start really, I'm sure there's more bases to cover yet. But it gets the topic moving anyway. Anyone makes improvements, be sure to post them.
BERESHEIT
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Post by Joakim Christiansen »

dell_jockey wrote:Joakim,

it works on XP, with minor alignment problems on the right side of the header bar.
Developing a program for Vista that looks the same on XP is like developing a web page for IE and make it look the same in FF. I really hate what Microsoft have done...
I like logic, hence I dislike humans but love computers.
Konne
Enthusiast
Enthusiast
Posts: 434
Joined: Thu May 12, 2005 9:15 pm

Post by Konne »

@netmaestro

Wow best exmaple for this I've ever seen. Thx very much.

There is only one question left. What Event is send when the [X] [_] Buttons etc need to be redrawn?
Apart from that Mrs Lincoln, how was the show?
User avatar
Rook Zimbabwe
Addict
Addict
Posts: 4322
Joined: Tue Jan 02, 2007 8:16 pm
Location: Cypress TX
Contact:

Post by Rook Zimbabwe »

NetMaestro I have done did learnt so much from you!

Now to create a few PNGs and a transparent window and frame it than a few image buttons and I will have my own window!!!
Binarily speaking... it takes 10 to Tango!!!

Image
http://www.bluemesapc.com/
Post Reply