Ownerdrawn resizable window frames

Share your advanced PureBasic knowledge/code with the community.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Ownerdrawn resizable window frames

Post by netmaestro »

* Updated for PB 5.31 *

Here is a small demonstration of how you can tap into #WM_NCCALCSIZE to give your window a custom caption height and frame thickness while maintaining the ability to resize on demand. Unfortunately, when you custom-draw a window frame you are stuck with doing your own systemmenu buttons as well, which adds a lot of hassle to the job. I've included a close button, but you can use the same logic and add minimize and max/restore to it too if desired. There is a GDI objects count displayed at 0,0 of the client area of the window, this serves two purposes: One, I want to keep an eye on leaks with all this GDI activity happening and Two, I want to display something at 0,0 to make sure the client area is being readjusted properly after resizes. The Status Bar is to keep an eye on the bottom and right of the client area. If everything looks to be showing where it ought to be, the calculations are coming out right. You can do a lot more than just use a basic pattern brush, like my demo is doing. Once you have your hands on that frame DC the sky's the limit. You can do really cool custom window frames of your own design. Anyway, on to the demo:

Code: Select all


;=================================================================== 
; Program:            Ownerdrawn Resizable Window Frame Demo 
; Author:             Lloyd Gallant (netmaestro) 
; Date:               August 28, 2007 
; Target OS:          Microsoft Windows All (I think) 
; Target Compiler:    PureBasic 4.xx and later 
; License:            Free, unrestricted, no warranty
;=================================================================== 

; Adjust these for different Caption height and frame thicknesses
Global gCaptionHeight   = 60
Global gFrameWidth      = 20
Global buttonsize       = 18
Global gCaptionTxtColor = #White

Structure NCCALCSIZE_PARAMS2
  rgrc.RECT[3]
  *lppos.WINDOWPOS
EndStructure

; read in button images for the 3 states 

UseJCALG1Packer()
*unpacked = AllocateMemory(3008)
UncompressMemory(?closebuttons, ?closebuttonsend-?closebuttons, *unpacked, MemorySize(*unpacked))
img0 = CatchImage(#PB_Any, *unpacked, 3008)
FreeMemory(*unpacked)

Global CB_Normal   = GrabImage(img0, #PB_Any,0,0,18,18) 
Global CB_Selected = GrabImage(img0, #PB_Any,18,0,18,18) 
Global CB_Pressed  = GrabImage(img0, #PB_Any,36,0,18,18) 

If buttonsize<>18
  ResizeImage(CB_Normal, buttonsize,buttonsize)
  ResizeImage(CB_Selected, buttonsize,buttonsize)
  ResizeImage(CB_Pressed, buttonsize,buttonsize)
EndIf

StartDrawing(ImageOutput(img0)) 
  Global gTranscolor = Point(0,0) 
StopDrawing() 
FreeImage(img0) 

Global gFrameTexture = CatchImage(#PB_Any, ?backbrush) 
Global hBrush = CreatePatternBrush_(ImageID(gFrameTexture))

Global gCloseButton_State = CB_Normal 

ProcedureDLL TransBlit(hdc, hBitmap, xStart, yStart, TransColor) 
  ; by netmaestro based on http://support.microsoft.com/kb/79212/EN-US/ 
  Define.POINT  ptSize 
  hdcTemp = CreateCompatibleDC_(hdc) 
  SelectObject_(hdcTemp, hBitmap) 
  GetObject_(hBitmap, SizeOf(BITMAP), bm.BITMAP) 
  ptSize\x = bm\bmWidth 
  ptSize\y = bm\bmHeight 
  DPtoLP_(hdcTemp, @ptSize, 1) 
  hdcBack   = CreateCompatibleDC_(hdc) 
  hdcObject = CreateCompatibleDC_(hdc) 
  hdcMem    = CreateCompatibleDC_(hdc) 
  hdcSave   = CreateCompatibleDC_(hdc) 
  bmAndBack   = CreateBitmap_(ptSize\x, ptSize\y, 1, 1, #Null) 
  bmAndObject = CreateBitmap_(ptSize\x, ptSize\y, 1, 1, #Null) 
  bmAndMem    = CreateCompatibleBitmap_(hdc, ptSize\x, ptSize\y) 
  bmSave      = CreateCompatibleBitmap_(hdc, ptSize\x, ptSize\y) 
  bmBackOld   = SelectObject_(hdcBack, bmAndBack) 
  bmObjectOld = SelectObject_(hdcObject, bmAndObject) 
  bmMemOld    = SelectObject_(hdcMem, bmAndMem) 
  bmSaveOld   = SelectObject_(hdcSave, bmSave) 
  SetMapMode_(hdcTemp, GetMapMode_(hdc)) 
  BitBlt_(hdcSave, 0, 0, ptSize\x, ptSize\y, hdcTemp, 0, 0, #SRCCOPY) 
  cColor = SetBkColor_(hdcTemp, TransColor) 
  BitBlt_(hdcObject, 0, 0, ptSize\x, ptSize\y, hdcTemp, 0, 0, #SRCCOPY) 
  SetBkColor_(hdcTemp, cColor) 
  BitBlt_(hdcBack, 0, 0, ptSize\x, ptSize\y, hdcObject, 0, 0, #NOTSRCCOPY) 
  BitBlt_(hdcMem, 0, 0, ptSize\x, ptSize\y, hdc, xStart, yStart, #SRCCOPY) 
  BitBlt_(hdcMem, 0, 0, ptSize\x, ptSize\y, hdcObject, 0, 0, #SRCAND) 
  BitBlt_(hdcTemp, 0, 0, ptSize\x, ptSize\y, hdcBack, 0, 0, #SRCAND) 
  BitBlt_(hdcMem, 0, 0, ptSize\x, ptSize\y, hdcTemp, 0, 0, #SRCPAINT) 
  BitBlt_(hdc, xStart, yStart, ptSize\x, ptSize\y, hdcMem, 0, 0, #SRCCOPY) 
  BitBlt_(hdcTemp, 0, 0, ptSize\x, ptSize\y, hdcSave, 0, 0, #SRCCOPY) 
  DeleteObject_(SelectObject_(hdcBack, bmBackOld)) 
  DeleteObject_(SelectObject_(hdcObject, bmObjectOld)) 
  DeleteObject_(SelectObject_(hdcMem, bmMemOld)) 
  DeleteObject_(SelectObject_(hdcSave, bmSaveOld)) 
  DeleteDC_(hdcMem) 
  DeleteDC_(hdcBack) 
  DeleteDC_(hdcObject) 
  DeleteDC_(hdcSave) 
  DeleteDC_(hdcTemp) 
EndProcedure 

Procedure WindowProc(hwnd, msg, wParam, lParam) 
    
  Static frameW 
  Static captionH
  Static buttonT

  oldproc = GetProp_(hwnd, "oldproc")
  result = oldproc

  Select msg 
    
    Case #WM_NCDESTROY
      RemoveProp_(hwnd, "oldproc")

    Case #WM_MOUSEMOVE 
      If gCloseButton_State <> CB_Normal 
        gCloseButton_State = CB_Normal 
        SendMessage_(hwnd, #WM_NCPAINT, 0,0) 
      EndIf 
      
    Case #WM_NCLBUTTONDOWN 
      GetWindowRect_(hwnd, wr.RECT) 
      cp.POINT 
      cp\x = lparam & $FFFF - wr\left 
      cp\y = lparam >> 16 - wr\top 

      br.RECT 
      br\left = wr\right-wr\left - frameW-buttonsize
      br\right = br\left+buttonsize 
      br\top = buttonT 
      br\bottom = br\top + buttonsize 
      
      If PtInRect_(br, cp\x|(cp\y<<32)) 
        gCloseButton_State = CB_Pressed 
        SendMessage_(hwnd, #WM_NCPAINT, 0,0) 
        result = 0 
      EndIf 
      
    Case #WM_NCLBUTTONUP 
      GetWindowRect_(hwnd, wr.RECT) 
      cp.POINT 
      cp\x = lparam & $FFFF - wr\left 
      cp\y = lparam >> 16 - wr\top 
            
      br.RECT 
      br\left = wr\right-wr\left - frameW-buttonsize
      br\right = br\left+buttonsize 
      br\top = buttonT 
      br\bottom = br\top + buttonsize 
      
      If PtInRect_(br, cp\x|(cp\y<<32)) 
        If gCloseButton_State = CB_Pressed 
          SendMessage_(hwnd, #WM_SYSCOMMAND, #SC_CLOSE, 0) 
        EndIf 
      Else 
        gCloseButton_State = CB_Normal 
        SendMessage_(hwnd, #WM_NCPAINT, 0,0) 
        result = 0 
      EndIf 
      
    Case #WM_NCMOUSEMOVE 
      GetWindowRect_(hwnd, wr.RECT) 
      cp.POINT 
      cp\x = lparam & $FFFF - wr\left 
      cp\y = lparam >> 16 - wr\top 
      
      br.RECT 
      br\left = wr\right-wr\left - frameW-buttonsize 
      br\right = br\left+buttonsize 
      br\top = buttonT 
      br\bottom = br\top + buttonsize 
      
      If PtInRect_(br, cp\x|(cp\y<<32)) 
        If GetAsyncKeyState_(#VK_LBUTTON) & 32768 
          If gCloseButton_State = CB_Pressed 
            SendMessage_(hwnd, #WM_NCPAINT, 0,0) 
          Else 
            If gCloseButton_State <> CB_Selected 
              gCloseButton_State = CB_Selected 
              SendMessage_(hwnd, #WM_NCPAINT, 0,0) 
            EndIf 
          EndIf 
        Else 
          If gCloseButton_State <> CB_Selected 
            gCloseButton_State = CB_Selected 
            SendMessage_(hwnd, #WM_NCPAINT, 0,0) 
          EndIf 
        EndIf 
      Else 
        If gCloseButton_State <> CB_Normal 
          gCloseButton_State = CB_Normal 
          SendMessage_(hwnd, #WM_NCPAINT, 0,0) 
        EndIf 
      EndIf    
      result = 0 
          
     Case #WM_NCCALCSIZE

       *np.NCCALCSIZE_PARAMS2 = lparam
    
        With *np\rgrc[0]
          \left    = *np\lppos\x + gFrameWidth
          \top     = *np\lppos\y + gCaptionHeight
          \right   = *np\lppos\x + *np\lppos\cx - gFrameWidth
          \bottom  = *np\lppos\y + *np\lppos\cy - gFrameWidth
        EndWith     

       captionH = *np\rgrc[0]\top - *np\lppos\y 
       frameW   = *np\rgrc[0]\left - *np\lppos\x
       buttonT = (captionH - buttonsize)/2

     
     If wparam=0
       result=0
     Else
       result =  #WVR_VALIDRECTS | #WVR_REDRAW 
     EndIf
          
    Case #WM_NCPAINT, #WM_NCACTIVATE 
      
      GetWindowRect_(hwnd, wr.RECT)
      new_w = wr\right - wr\left 
      new_h = wr\bottom - wr\top 
      hdc = GetWindowDC_(hwnd) 
      hdctemp = CreateCompatibleDC_(hdc)
      hrgn = CreateRectRgn_(-1,-1,new_w+1, new_h+1) 
      hrgn2 = CreateRectRgn_(frameW,captionH,new_w-frameW,new_h-frameW) 
      CombineRgn_(hrgn, hrgn, hrgn2, #RGN_XOR) 
      SelectClipRgn_(hdc, hrgn) 
      imgtemp = CreateImage(#PB_Any, new_w+2,new_h+2, #PB_Image_DisplayFormat)
      hBitmap = ImageID(imgtemp)
      SelectObject_(hdctemp, hBitmap)
      SelectObject_(hdctemp, hBrush) 
      Rectangle_(hdctemp,-1,-1,new_w+1, new_h+1) 
      ; Window title
      wt$ = Space(100)
      GetWindowText_(hwnd, @wt$, 99)
      SetBkMode_(hdctemp, #TRANSPARENT)
      SetTextColor_(hdctemp, gCaptionTxtColor)
      TextOut_(hdctemp, frameW,captionH/2-7,wt$, Len(wt$))
      ; Buttons
      If IsImage(gCloseButton_State) 
        TransBlit(hdctemp, ImageID(gCloseButton_State), new_w - frameW-buttonsize, buttonT, gTranscolor) 
        DeleteDC_(buttondc) 
      EndIf 
      BitBlt_(hdc,0,0,new_w+1, new_h+1,hdctemp,0,0,#SRCCOPY)
      DeleteObject_(hBitmap)
      DeleteDC_(hdctemp)
      ReleaseDC_(hwnd, hdc) 
      DeleteObject_(hrgn) 
      DeleteObject_(hrgn2) 
      result = 0 

  EndSelect 
  
  If result = oldproc
    ProcedureReturn CallWindowProc_(oldproc, hwnd, msg, wparam, lparam)
  Else
    ProcedureReturn result
  EndIf
  
EndProcedure 

Procedure MonitorButtons(hwnd) 
  Repeat 
    GetWindowRect_(hwnd, @wr.RECT) 
    GetCursorPos_(@cp.POINT) 
    ; if the cursor is outside the window, the CloseButton 
    ; must show normal. All other cases are covered in the callback. 
    If Not PtInRect_(wr, cp\x|(cp\y<<32)) 
      If gCloseButton_State <> CB_Normal 
        gCloseButton_State = CB_Normal 
        SendMessage_(hwnd, #WM_NCPAINT, 0,0) 
      EndIf 
    EndIf 
    Delay(15) 
  ForEver 
EndProcedure 

Procedure cb(hwnd, msg, wparam, lparam)
  result = #PB_ProcessPureBasicEvents

  ProcedureReturn result
EndProcedure

OpenWindow(0,0,0,320,240,"Ownerdrawn Frame",#PB_Window_SizeGadget|#PB_Window_ScreenCentered)
StickyWindow(0,1)
TextGadget(0,0,0,150,20,"")
SetGadgetColor(0,#PB_Gadget_BackColor, #White) 
SetWindowColor(0, #White)
SetProp_(WindowID(0), "oldproc", SetWindowLong_(WindowID(0), #GWL_WNDPROC, @WindowProc())) 
CreateStatusBar(0, WindowID(0))

; dry-fire the WM_NCCALCSIZE and WM_NCPAINT events:
SetWindowPos_(WindowID(0),0,0,0,0,0,#SWP_NOMOVE|#SWP_NOSIZE|#SWP_NOZORDER|#SWP_FRAMECHANGED)

; a thread ensures no mistakes in resetting the CloseButton image to normal 
CreateThread(@MonitorButtons(), WindowID(0)) 

ProcessHandle = OpenProcess_(#PROCESS_ALL_ACCESS,#False,GetCurrentProcessId_());

lastgdicount = 0
Repeat 
  ev = WaitWindowEvent()
  gdicount = GetGuiResources_(ProcessHandle, 0) ; 0 = #GR_GDIOBJECTS
  If gdicount <> lastgdicount
    lastgdicount = gdicount
    SetGadgetText(0,"GDI Object Count: "+Str(gdicount))
  EndIf
Until ev=#PB_Event_CloseWindow 

DeleteObject_(hBrush)

DataSection 
  backbrush:         
  IncludeBinary #PB_Compiler_Home+"Examples\Sources\Data\Background.bmp"
  closebuttons:      
  Data.b $4A,$43,$C0,$0B,$00,$00,$72,$EC,$2F,$DE,$BC,$A9,$D0,$20,$69,$14,$59,$08,$18,$CA
  Data.b $08,$B0,$01,$25,$89,$22,$3C,$06,$18,$23,$98,$C4,$40,$50,$FF,$14,$60,$12,$79,$E2
  Data.b $7C,$80,$D2,$15,$A3,$B1,$CC,$74,$4E,$A2,$C0,$48,$30,$0D,$FD,$EF,$04,$6E,$65,$03
  Data.b $D0,$8C,$F4,$5C,$2E,$D4,$60,$15,$F5,$96,$27,$65,$63,$9D,$36,$AD,$9E,$F5,$57,$29
  Data.b $C7,$AD,$00,$2B,$53,$E3,$81,$15,$5D,$18,$14,$42,$1B,$50,$01,$C0,$58,$27,$67,$FB
  Data.b $04,$7A,$6A,$EC,$A1,$59,$4F,$42,$1B,$E0,$D0,$09,$84,$60,$6C,$B2,$63,$B5,$A3,$4F
  Data.b $99,$77,$19,$A0,$69,$F2,$27,$50,$45,$4E,$8A,$8D,$D5,$42,$B6,$D3,$F3,$ED,$77,$DC
  Data.b $19,$E8,$45,$7D,$6E,$4A,$A0,$3F,$E7,$36,$97,$60,$FE,$1F,$42,$21,$B4,$81,$91,$5A
  Data.b $2D,$74,$5B,$A1,$23,$A7,$55,$CA,$ED,$A4,$C7,$CA,$15,$B9,$60,$59,$BB,$2E,$09,$85
  Data.b $40,$3D,$CF,$9B,$B5,$D0,$27,$FA,$92,$B6,$E8,$4E,$A5,$32,$E2,$1D,$6C,$55,$66,$1D
  Data.b $4F,$96,$59,$AD,$E6,$CD,$E9,$06,$AC,$FC,$82,$F8,$B2,$58,$B4,$65,$2D,$74,$A7,$E2
  Data.b $64,$2E,$3F,$ED,$CB,$D6,$4C,$41,$1D,$F9,$93,$A6,$EC,$F6,$C0,$46,$53,$92,$10,$DA
  Data.b $C0,$6B,$B3,$16,$3A,$A1,$42,$6A,$CC,$90,$D7,$D5,$3E,$91,$52,$B3,$D2,$87,$CE,$2B
  Data.b $97,$E4,$95,$F9,$D3,$AA,$24,$D0,$61,$1A,$4C,$EB,$D7,$E7,$0A,$7A,$80,$07,$A1,$10
  Data.b $DA,$A0,$79,$94,$16,$3C,$44,$7F,$AE,$EE,$DE,$AC,$56,$E1,$C5,$87,$B5,$5A,$EA,$79
  Data.b $B4,$5B,$3E,$45,$0F,$56,$A7,$9D,$50,$BA,$02,$6F,$C0,$D2,$97,$C0,$4E,$AD,$D6,$42
  Data.b $27,$9C,$13,$E1,$43,$7D,$59,$B0,$71,$A5,$40,$23,$FE,$BF,$99,$19,$8B,$3E,$71,$4C
  Data.b $91,$3D,$74,$67,$F6,$7F,$7C,$C0,$34,$5F,$0D,$AA,$A0,$07,$A1,$13,$0A,$A1,$F1,$A5
  Data.b $44,$6B,$56,$1C,$90,$DA,$8E,$B5,$AB,$89,$D2,$A5,$5E,$6D,$BD,$BD,$ED,$DB,$B9,$CE
  Data.b $A7,$5E,$AD,$5F,$35,$59,$80,$0D,$D8,$F4,$B4,$41,$15,$F4,$2D,$74,$42,$21,$C7,$48
  Data.b $CD,$68,$DD,$AA,$7E,$6D,$B2,$55,$D1,$9F,$EF,$DB,$F6,$FB,$FA,$B1,$53,$CF,$B5,$3D
  Data.b $5B,$AE,$80,$B9,$77,$EB,$54,$41,$0F,$D8,$27,$14,$42,$1B,$2A,$A9,$D5,$42,$79,$8D
  Data.b $23,$15,$99,$EF,$7F,$C8,$A1,$BC,$97,$12,$C7,$CD,$52,$4E,$01,$53,$D0,$87,$32,$93
  Data.b $68,$97,$A0,$07,$78,$C0,$0A,$A1,$0D,$AA,$43,$6B,$A1,$13,$D6,$22,$B5,$A4,$5F,$72
  Data.b $07,$4B,$B8,$F0,$C4,$30,$09,$00,$33,$8A,$69,$F6,$25,$D9,$AE,$60,$AB,$B3,$81,$12
  Data.b $70,$00,$68,$83,$2A,$E8,$52,$EB,$84,$42,$1A,$0A,$F1,$24,$86,$55,$AF,$16,$CD,$9D
  Data.b $F8,$E5,$9C,$A3,$3C,$F4,$FF,$EE,$DA,$D0,$85,$DF,$D6,$2B,$00,$F1,$DD,$7E,$D0,$03
  Data.b $25,$D0,$85,$D0,$06,$55,$6A,$B5,$D0,$09,$E3,$47,$83,$4A,$EF,$FF,$C4,$1C,$52,$94
  Data.b $22,$19,$FB,$3E,$8E,$5A,$EF,$BD,$10,$98,$1F,$7E,$4B,$19,$00,$C4,$70,$FD,$E8,$81
  Data.b $12,$70,$42,$68,$83,$02,$B6,$5A,$E8,$84,$C4,$4E,$7D,$B8,$DD,$6B,$58,$D6,$96,$F2
  Data.b $95,$72,$61,$7E,$27,$5B,$F8,$70,$BC,$32,$EC,$99,$80,$9C,$AB,$D7,$FA,$1F,$09,$34
  Data.b $80,$85,$41,$15,$F4,$40,$74,$42,$21,$B4,$D6,$5C,$5B,$2D,$31,$BC,$28,$50,$AE,$58
  Data.b $F9,$E8,$AF,$D7,$2C,$65,$39,$C6,$D9,$C9,$EC,$C6,$01,$A3,$B8,$60,$C1,$34,$D3,$34
  Data.b $00,$FD,$1B,$30,$F7,$50,$42,$27,$14,$42,$87,$B3,$47,$D5,$6D,$71,$A3,$40,$BF,$ED
  Data.b $2F,$D8,$E2,$B8,$FC,$09,$E6,$39,$34,$3F,$E5,$C1,$93,$43,$C2,$6F,$EF,$84,$FF,$7F
  Data.b $D5,$52,$80,$12,$68,$00,$68,$83,$2A,$28,$5A,$E8,$84,$42,$44,$A2,$BC,$B6,$CD,$2E
  Data.b $91,$D4,$CA,$6E,$97,$90,$B4,$6A,$BB,$4B,$36,$13,$A6,$F9,$2F,$49,$EE,$A7,$0F,$B5
  Data.b $06,$98,$84,$36,$A0,$02,$AD,$85,$4E,$28,$E5,$18,$A9,$19,$BC,$67,$EB,$DF,$CF,$17
  Data.b $AD,$FD,$FF,$03,$B3,$C5,$F4,$8B,$75,$6A,$D4,$1A,$80,$3F,$42,$68,$03,$2B,$7D,$5A
  Data.b $E8,$84,$A4,$56,$F4,$27,$B6,$3F,$8C,$46,$76,$4B,$09,$DC,$3A,$CC,$A9,$01,$1F,$EB
  Data.b $84,$84,$D7,$86,$E0,$CA,$00,$FD,$A5,$2F,$C0,$03,$DA,$D0,$85,$D0,$06,$55,$6A,$B5
  Data.b $D0,$09,$4E,$76,$2C,$45,$DE,$CD,$96,$E5,$D9,$F0,$68,$27,$36,$ED,$77,$CA,$7A,$AF
  Data.b $A7,$A6,$FE,$DB,$46,$7D,$07,$4A,$E0,$00,$A1,$0D,$AA,$A0,$6B,$A1,$13,$0A,$B8,$C1
  Data.b $0C,$46,$5F,$EF,$D9,$E1,$F5,$F7,$45,$7B,$06,$28,$C0,$69,$B6,$76,$BF,$5F,$9C,$F3
  Data.b $27,$8C,$BD,$4F,$C3,$96,$40,$09,$60,$63,$B3,$41,$15,$F4,$FF,$BF,$69,$F3,$16,$F6
  Data.b $73,$02,$28,$71,$48,$AD,$BF,$69,$19,$00,$9A,$01,$AD,$7E,$D0,$C0,$80,$01,$3D,$FF
  Data.b $0B,$66,$F4,$00,$67,$63,$21,$B8,$41,$15,$5A,$2D,$74,$02,$48,$A1,$E2,$90,$B6,$6C
  Data.b $EB,$9F,$3E,$2D,$80,$76,$05,$BF,$76,$12,$58,$8D,$03,$A0,$93,$1A,$30,$94,$50,$05
  Data.b $3D,$40,$9D,$50,$08,$6D,$31,$3B,$55,$0B,$0F,$66,$8B,$9B,$FC,$05,$53,$FE,$66,$A1
  Data.b $37,$B5,$B9,$59,$FE,$BD,$40,$05,$3D,$40,$C7,$7E,$C1,$78,$9F,$13,$FA,$43,$19,$6A
  Data.b $B5,$F0,$4B,$DA,$E6,$A9,$AE,$ED,$D2,$E1,$29,$8B,$01,$14,$EF,$86,$E5,$4F,$00,$65
  Data.b $63,$F7,$E1,$6C,$15,$F4,$68,$C1,$13,$0E,$89,$D4,$DC,$A3,$F1,$90,$50,$AE,$09,$65
  Data.b $AD,$5A,$E3,$38,$00,$DB,$F7,$DE,$1D,$43,$9A,$75,$32,$E8,$81,$06,$D0,$ED,$AB,$82
  Data.b $1E,$28,$16,$3A,$01,$0F,$35,$7B,$54,$87,$52,$C4,$D9,$A1,$FC,$D6,$BF,$D9,$D4,$FE
  Data.b $0C,$10,$41,$DE,$BB,$4B,$38,$6B,$DA,$A2,$6C,$E0,$1A,$20,$0D,$AA,$80,$07,$B2,$A5
  Data.b $1E,$A0,$62,$FD,$CC,$0D,$7A,$21,$BC,$2C,$AC,$E6,$C2,$00,$D5,$9D,$42,$B7,$19,$6A
  Data.b $13,$A1,$0F,$6C,$03,$85,$42,$1B,$54,$41,$D5,$42,$27,$14,$80,$92,$1A,$A9,$E0,$6D
  Data.b $DB,$FA,$19,$F2,$70,$19,$4B,$B8,$53,$2A,$FE,$3B,$16,$F0,$3C,$73,$12,$07,$12,$68
  Data.b $00,$C4,$83,$2A,$E8,$81,$E8,$84,$42,$68,$41,$25,$B5,$5A,$0A,$EB,$6F,$41,$FF,$86
  Data.b $E1,$52,$66,$94,$C1,$1A,$E4,$BD,$8D,$B3,$F0,$99,$E8,$D1,$71,$56,$02,$0D,$42,$21
  Data.b $B4,$01,$91,$5A,$2D,$74,$21,$35,$8E,$28,$EF,$96,$8D,$4F,$4A,$DD,$B1,$F4,$D4,$DF
  Data.b $BB,$76,$55,$EE,$FB,$B8,$00,$9B,$7D,$06,$D0,$03,$25,$D0,$85,$D0,$06,$55,$6A,$B5
  Data.b $D0,$09,$B7,$AE,$2F,$4C,$B9,$14,$F3,$9C,$BC,$D9,$B1,$94,$D7,$00,$FF,$7D,$E6,$71
  Data.b $49,$70,$C6,$DD,$8B,$93,$D0,$00,$ED,$ED,$55,$D0,$03,$25,$09,$85,$D0,$06,$4F,$A4
  Data.b $B5,$D0,$CF,$13,$CB,$B5,$5F,$F1,$87,$0C,$9D,$42,$25,$E5,$71,$6D,$30,$EF,$1C,$BA
  Data.b $FC,$F7,$C7,$74,$21,$FF,$09,$34,$00,$7F,$BB,$E5,$F5,$40,$7F,$CF,$52,$CE,$5A,$E8
  Data.b $04,$FF,$9E,$4F,$FC,$AD,$B3,$FD,$4A,$B2,$7B,$B1,$53,$DB,$FB,$FF,$5D,$FB,$9A,$3E
  Data.b $AD,$D3,$3F,$77,$2C,$E3,$2B,$81,$06,$D0,$A1,$0D,$EC,$D8,$6A,$A1,$13,$0A,$14,$52
  Data.b $F3,$DA,$E7,$BE,$0E,$AA,$29,$74,$39,$77,$7D,$DD,$B8,$E8,$CD,$5C,$92,$FA,$3C,$71
  Data.b $DB,$BE,$38,$B0,$5F,$A1,$07,$F3,$9D,$9F,$F4,$84,$29,$EA,$27,$7D,$C4,$9A,$2A,$F0
  Data.b $1B,$94,$21,$B4,$41,$6E,$3D,$2D,$74,$42,$22,$D4,$0F,$2B,$12,$46,$55,$BC,$CC,$97
  Data.b $01,$F4,$FE,$01,$C9,$92,$4E,$64,$FB,$AE,$86,$37,$48,$99,$66,$C1,$9D,$D1,$38,$6C
  Data.b $87,$95,$2A,$E8,$01,$12,$5B,$FD,$35,$EC,$82,$27,$54,$E6,$D3,$38,$33,$D4,$CD,$2A
  Data.b $BC,$D2,$B4,$5C,$CF,$97,$FE,$85,$6A,$FA,$4B,$47,$AD,$1A,$CF,$E0,$BC,$89,$15,$DB
  Data.b $F8,$A6,$B8,$60,$F5,$D7,$09,$34,$00,$7C,$41,$15,$F4,$40,$74,$42,$21,$B4,$6A,$5C
  Data.b $5B,$2D,$BD,$5F,$BB,$4C,$BB,$0F,$CC,$F7,$53,$FF,$93,$15,$DD,$D9,$39,$6B,$D5,$97
  Data.b $F7,$1E,$7F,$9A,$32,$7D,$EE,$49,$4B,$66,$4F,$56,$8F,$01,$A9,$2F,$5F,$4A,$17,$E9
  Data.b $CE,$FA,$50,$08,$6D,$80,$EA,$53,$0B,$9D,$4F,$3A,$94,$3D,$FF,$9C,$07,$17,$37,$33
  Data.b $80,$E1,$B3,$61,$29,$B4,$DC,$94,$69,$EB,$6B,$7E,$63,$76,$17,$FF,$BA,$2F,$97,$CA
  Data.b $97,$DC,$93,$40,$E6,$FE,$49,$35,$BE,$35,$B4,$01,$63,$A6,$2D,$74,$42,$21,$4B,$89
  Data.b $36,$43,$7C,$C2,$73,$29,$B5,$FB,$54,$8B,$67,$BA,$07,$4B,$23,$CA,$CF,$2C,$97,$BD
  Data.b $5A,$78,$EB,$3B,$55,$E9,$31,$62,$CF,$00,$50,$05,$3D,$A0,$9D,$50,$08,$6D,$37,$35
  Data.b $5A,$0B,$FA,$84,$D4,$90,$E4,$C1,$BE,$93,$0C,$05,$78,$3F,$E7,$73,$76,$0C,$F4,$7F
  Data.b $DD,$A2,$DD,$99,$02,$FC,$4F,$03,$C0,$AF,$31,$20,$3E,$ED,$A8,$3B,$46,$EF,$B4,$C1
  Data.b $FF,$E0,$2D,$74,$42,$21,$F4,$6D,$74,$67,$5E,$D3,$A3,$DE,$69,$E1,$B4,$1E,$E9,$AA
  Data.b $29,$B8,$CA,$F5,$D6,$14,$21,$21,$79,$68,$01,$14,$FF,$C8,$32,$1A,$02,$8D,$EB,$AA
  Data.b $7D,$E0,$84,$42,$70,$83,$EA,$CD,$5A,$E8,$1F,$85,$69,$5D,$79,$BE,$77,$9D,$9E,$9F
  Data.b $7A,$71,$CE,$F4,$89,$67,$F9,$67,$84,$2C,$2F,$5C,$33,$45,$86,$9F,$D2,$C9,$05,$3D
  Data.b $60,$03,$50,$08,$6D,$50,$9D,$59,$0B,$9D,$60,$E8,$9E,$27,$67,$3F,$6B,$95,$AF,$33
  Data.b $AE,$33,$79,$DC,$FD,$3D,$2F,$5F,$7B,$BF,$B8,$90,$A7,$F0,$6C,$60,$9A,$07,$D0,$06
  Data.b $94,$F2,$B5,$D0,$09,$85,$A2,$5B,$66,$74,$E8,$28,$EB,$8D,$CD,$E8,$A8,$C0,$8A,$6E
  Data.b $B4,$DE,$E8,$CD,$06,$70,$BF,$75,$EB,$9C,$F4,$BC,$71,$AB,$49,$BA,$5D,$CB,$3A,$A1
  Data.b $10,$BC,$6E,$F7,$BF,$16,$0D,$75,$A8,$45,$CA,$A6,$50,$FD,$33,$60,$53,$AB,$81,$69
  Data.b $8C,$62,$14,$82,$09,$B8,$BD,$AB,$5D,$27,$53,$25,$03,$E6,$6D,$DE,$4C,$CE,$B0,$27
  Data.b $9C,$BC,$18,$EB,$84,$42,$88,$44,$08,$00,$00,$00,$00,$00
  closebuttonsend:
EndDataSection 
Last edited by netmaestro on Wed Feb 04, 2015 8:48 am, edited 6 times in total.
BERESHEIT
Dare
Addict
Addict
Posts: 1965
Joined: Mon May 29, 2006 1:01 am
Location: Outback

Post by Dare »

Very nice!
Dare2 cut down to size
rsts
Addict
Addict
Posts: 2736
Joined: Wed Aug 24, 2005 8:39 am
Location: Southwest OH - USA

Post by rsts »

Another lesson from the maestro :D

Thanks.
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Post by Mistrel »

Impressive! With a web gadget inside you can make something really unique.
gnozal
PureBasic Expert
PureBasic Expert
Posts: 4229
Joined: Sat Apr 26, 2003 8:27 am
Location: Strasbourg / France
Contact:

Post by gnozal »

Yes, very impressive.
Be aware that it will not work with Win NT4/9x/Me because of GetGuiResources_().
For free libraries and tools, visit my web site (also home of jaPBe V3 and PureFORM).
Nico
Enthusiast
Enthusiast
Posts: 274
Joined: Sun Jan 11, 2004 11:34 am
Location: France

Post by Nico »

For have the system menu:

Code: Select all

OpenWindow(0,0,0,320,240,"Ownerdrawn Frame",#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget|#PB_Window_ScreenCentered)
and

Code: Select all

    Case #WM_NCHITTEST 
        #HTCLOSE=20
        #HTCAPTION=2
        #HTMAXBUTTON=9
        #HTMINBUTTON=8
        result=DefWindowProc_(hwnd, msg, wparam, lparam)
        Debug "----------------------"
        Debug result
        If result=#HTCLOSE Or result=#HTMAXBUTTON  Or result=#HTMINBUTTON
          result=#HTCAPTION
        EndIf 
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

It's not that easy, unfortunately. When you ownerdraw the frame, the buttons don't show through. I originally thought I could solve it by cutting rectangles out of the frame region to let the buttons show through, but then I realized that the button sizes and locations are different depending on which theme if any is being used on the system. Of all the options available I judged that the easiest way in the end is to just use some CustomButtons code and do it myself.
BERESHEIT
Nico
Enthusiast
Enthusiast
Posts: 274
Joined: Sun Jan 11, 2004 11:34 am
Location: France

Post by Nico »

It's just a trick to have the system menu, if you don't track the message #WM_NCHITTEST, buttons system will appear; sure is needed CustomButtons.
User avatar
DoubleDutch
Addict
Addict
Posts: 3220
Joined: Thu Aug 07, 2003 7:01 pm
Location: United Kingdom
Contact:

Post by DoubleDutch »

Looks great, works with vista no problems. :)
https://deluxepixel.com <- My Business website
https://reportcomplete.com <- School end of term reports system
Sparkie
PureBatMan Forever
PureBatMan Forever
Posts: 2307
Joined: Tue Feb 10, 2004 3:07 am
Location: Ohio, USA

Post by Sparkie »

Nice work netmaestro 8)
What goes around comes around.

PB 5.21 LTS (x86) - Windows 8.1
klaver
Enthusiast
Enthusiast
Posts: 147
Joined: Wed Jun 28, 2006 6:55 pm
Location: Schröttersburg

Re: Ownerdrawn resizable window frames

Post by klaver »

Sorry for bumping this thread, but I get a (false) positive from my Avast when compiled with PB 4.31.
Avast 4.8.1351.0 2009.09.27 Win32:SkiMorph
Any ideas why this happens?
Image
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Re: Ownerdrawn resizable window frames

Post by PB »

Don't know, but the code doesn't compile with v4.40 B3 at all.
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
User avatar
Hroudtwolf
Addict
Addict
Posts: 803
Joined: Sat Feb 12, 2005 3:35 am
Location: Germany(Hessen)
Contact:

Re: Ownerdrawn resizable window frames

Post by Hroudtwolf »

Take this.... :)

Code: Select all

;===================================================================
; Program:              Ownerdrawn Resizable Window Frame Demo
; Author:               Lloyd Gallant (netmaestro)
; Date:                 August 28, 2007
; Target OS:            Microsoft Windows All (I think)
; Target Compiler:      PureBasic 4.xx and later
; License:              Free, unrestricted, no warranty
; Modified for PB4.4x:  Hroudtwolf
;===================================================================

; Adjust these for different Caption height and frame thicknesses
Global gCaptionHeight   = 60
Global gFrameWidth      = 20
Global buttonsize       = 18
Global gCaptionTxtColor = #White



; read in button images for the 3 states

img0 = CatchImage(#PB_Any, ?closebuttons, 3008)

*unpacked = AllocateMemory(3008)
UnpackMemory(?closebuttons, *unpacked)
img0 = CatchImage(#PB_Any, *unpacked, 3008)
FreeMemory(*unpacked)

Global CB_Normal   = GrabImage(img0, #PB_Any,0,0,18,18)
Global CB_Selected = GrabImage(img0, #PB_Any,18,0,18,18)
Global CB_Pressed  = GrabImage(img0, #PB_Any,36,0,18,18)

If buttonsize<>18
  ResizeImage(CB_Normal, buttonsize,buttonsize)
  ResizeImage(CB_Selected, buttonsize,buttonsize)
  ResizeImage(CB_Pressed, buttonsize,buttonsize)
EndIf

StartDrawing(ImageOutput(img0))
  Global gTranscolor = Point(0,0)
StopDrawing()
FreeImage(img0)

Global gFrameTexture = CatchImage(#PB_Any, ?backbrush)
Global hBrush = CreatePatternBrush_(ImageID(gFrameTexture))

Global gCloseButton_State = CB_Normal

ProcedureDLL TransBlit(hdc, hBitmap, xStart, yStart, TransColor)
  ; by netmaestro based on http://support.microsoft.com/kb/79212/EN-US/
  Define.POINT  ptSize
  hdcTemp = CreateCompatibleDC_(hdc)
  SelectObject_(hdcTemp, hBitmap)
  GetObject_(hBitmap, SizeOf(BITMAP), bm.BITMAP)
  ptSize\x = bm\bmWidth
  ptSize\y = bm\bmHeight
  DPtoLP_(hdcTemp, @ptSize, 1)
  hdcBack   = CreateCompatibleDC_(hdc)
  hdcObject = CreateCompatibleDC_(hdc)
  hdcMem    = CreateCompatibleDC_(hdc)
  hdcSave   = CreateCompatibleDC_(hdc)
  bmAndBack   = CreateBitmap_(ptSize\x, ptSize\y, 1, 1, #Null)
  bmAndObject = CreateBitmap_(ptSize\x, ptSize\y, 1, 1, #Null)
  bmAndMem    = CreateCompatibleBitmap_(hdc, ptSize\x, ptSize\y)
  bmSave      = CreateCompatibleBitmap_(hdc, ptSize\x, ptSize\y)
  bmBackOld   = SelectObject_(hdcBack, bmAndBack)
  bmObjectOld = SelectObject_(hdcObject, bmAndObject)
  bmMemOld    = SelectObject_(hdcMem, bmAndMem)
  bmSaveOld   = SelectObject_(hdcSave, bmSave)
  SetMapMode_(hdcTemp, GetMapMode_(hdc))
  BitBlt_(hdcSave, 0, 0, ptSize\x, ptSize\y, hdcTemp, 0, 0, #SRCCOPY)
  cColor = SetBkColor_(hdcTemp, TransColor)
  BitBlt_(hdcObject, 0, 0, ptSize\x, ptSize\y, hdcTemp, 0, 0, #SRCCOPY)
  SetBkColor_(hdcTemp, cColor)
  BitBlt_(hdcBack, 0, 0, ptSize\x, ptSize\y, hdcObject, 0, 0, #NOTSRCCOPY)
  BitBlt_(hdcMem, 0, 0, ptSize\x, ptSize\y, hdc, xStart, yStart, #SRCCOPY)
  BitBlt_(hdcMem, 0, 0, ptSize\x, ptSize\y, hdcObject, 0, 0, #SRCAND)
  BitBlt_(hdcTemp, 0, 0, ptSize\x, ptSize\y, hdcBack, 0, 0, #SRCAND)
  BitBlt_(hdcMem, 0, 0, ptSize\x, ptSize\y, hdcTemp, 0, 0, #SRCPAINT)
  BitBlt_(hdc, xStart, yStart, ptSize\x, ptSize\y, hdcMem, 0, 0, #SRCCOPY)
  BitBlt_(hdcTemp, 0, 0, ptSize\x, ptSize\y, hdcSave, 0, 0, #SRCCOPY)
  DeleteObject_(SelectObject_(hdcBack, bmBackOld))
  DeleteObject_(SelectObject_(hdcObject, bmObjectOld))
  DeleteObject_(SelectObject_(hdcMem, bmMemOld))
  DeleteObject_(SelectObject_(hdcSave, bmSaveOld))
  DeleteDC_(hdcMem)
  DeleteDC_(hdcBack)
  DeleteDC_(hdcObject)
  DeleteDC_(hdcSave)
  DeleteDC_(hdcTemp)
EndProcedure

Procedure WindowProc(hwnd, msg, wParam, lParam)
   
  Static frameW
  Static captionH
  Static buttonT

  oldproc = GetProp_(hwnd, "oldproc")
  result = oldproc

  Select msg
   
    Case #WM_NCDESTROY
      RemoveProp_(hwnd, "oldproc")

    Case #WM_MOUSEMOVE
      If gCloseButton_State <> CB_Normal
        gCloseButton_State = CB_Normal
        SendMessage_(hwnd, #WM_NCPAINT, 0,0)
      EndIf
     
    Case #WM_NCLBUTTONDOWN
      GetWindowRect_(hwnd, wr.RECT)
      cp.POINT
      cp\x = lparam & $FFFF - wr\left
      cp\y = lparam >> 16 - wr\top

      br.RECT
      br\left = wr\right-wr\left - frameW-buttonsize
      br\right = br\left+buttonsize
      br\top = buttonT
      br\bottom = br\top + buttonsize
     
      If PtInRect_(br, cp)
        gCloseButton_State = CB_Pressed
        SendMessage_(hwnd, #WM_NCPAINT, 0,0)
        result = 0
      EndIf
     
    Case #WM_NCLBUTTONUP
      GetWindowRect_(hwnd, wr.RECT)
      cp.POINT
      cp\x = lparam & $FFFF - wr\left
      cp\y = lparam >> 16 - wr\top
           
      br.RECT
      br\left = wr\right-wr\left - frameW-buttonsize
      br\right = br\left+buttonsize
      br\top = buttonT
      br\bottom = br\top + buttonsize
     
      If PtInRect_(br, cp)
        If gCloseButton_State = CB_Pressed
          SendMessage_(hwnd, #WM_SYSCOMMAND, #SC_CLOSE, 0)
        EndIf
      Else
        gCloseButton_State = CB_Normal
        SendMessage_(hwnd, #WM_NCPAINT, 0,0)
        result = 0
      EndIf
     
    Case #WM_NCMOUSEMOVE
      GetWindowRect_(hwnd, wr.RECT)
      cp.POINT
      cp\x = lparam & $FFFF - wr\left
      cp\y = lparam >> 16 - wr\top
     
      br.RECT
      br\left = wr\right-wr\left - frameW-buttonsize
      br\right = br\left+buttonsize
      br\top = buttonT
      br\bottom = br\top + buttonsize
     
      If PtInRect_(br, cp)
        If GetAsyncKeyState_(#VK_LBUTTON) & 32768
          If gCloseButton_State = CB_Pressed
            SendMessage_(hwnd, #WM_NCPAINT, 0,0)
          Else
            If gCloseButton_State <> CB_Selected
              gCloseButton_State = CB_Selected
              SendMessage_(hwnd, #WM_NCPAINT, 0,0)
            EndIf
          EndIf
        Else
          If gCloseButton_State <> CB_Selected
            gCloseButton_State = CB_Selected
            SendMessage_(hwnd, #WM_NCPAINT, 0,0)
          EndIf
        EndIf
      Else
        If gCloseButton_State <> CB_Normal
          gCloseButton_State = CB_Normal
          SendMessage_(hwnd, #WM_NCPAINT, 0,0)
        EndIf
      EndIf   
      result = 0
         
     Case #WM_NCCALCSIZE
       *np.NCCALCSIZE_PARAMS = lparam
 
        With *np\rgrc[0]
          \left    = *np\lppos\x + gFrameWidth
          \top     = *np\lppos\y + gCaptionHeight
          \right   = *np\lppos\x + *np\lppos\cx - gFrameWidth
          \bottom  = *np\lppos\y + *np\lppos\cy - gFrameWidth
        EndWith     
       
       captionH = *np\rgrc[0]\top - *np\lppos\y
       frameW   = *np\rgrc[0]\left - *np\lppos\x
       buttonT = (captionH - buttonsize)/2
       
     result =  #WVR_VALIDRECTS | #WVR_REDRAW
         
    Case #WM_NCPAINT, #WM_NCACTIVATE
     
      GetWindowRect_(hwnd, wr.RECT)
      new_w = wr\right - wr\left
      new_h = wr\bottom - wr\top
      hdc = GetWindowDC_(hwnd)
      hdctemp = CreateCompatibleDC_(hdc)
      hrgn = CreateRectRgn_(-1,-1,new_w+1, new_h+1)
      hrgn2 = CreateRectRgn_(frameW,captionH,new_w-frameW,new_h-frameW)
      CombineRgn_(hrgn, hrgn, hrgn2, #RGN_XOR)
      SelectClipRgn_(hdc, hrgn)
      imgtemp = CreateImage(#PB_Any, new_w+2,new_h+2, #PB_Image_DisplayFormat)
      hBitmap = ImageID(imgtemp)
      SelectObject_(hdctemp, hBitmap)
      SelectObject_(hdctemp, hBrush)
      Rectangle_(hdctemp,-1,-1,new_w+1, new_h+1)
      ; Window title
      wt$ = Space(100)
      GetWindowText_(hwnd, @wt$, 99)
      SetBkMode_(hdctemp, #TRANSPARENT)
      SetTextColor_(hdctemp, gCaptionTxtColor)
      TextOut_(hdctemp, frameW,captionH/2-7,wt$, Len(wt$))
      ; Buttons
      If IsImage(gCloseButton_State)
        TransBlit(hdctemp, ImageID(gCloseButton_State), new_w - frameW-buttonsize, buttonT, gTranscolor)
        DeleteDC_(buttondc)
      EndIf
      BitBlt_(hdc,0,0,new_w+1, new_h+1,hdctemp,0,0,#SRCCOPY)
      DeleteObject_(hBitmap)
      DeleteDC_(hdctemp)
      ReleaseDC_(hwnd, hdc)
      DeleteObject_(hrgn)
      DeleteObject_(hrgn2)
      result = 0

  EndSelect
 
  If result = oldproc
    ProcedureReturn CallWindowProc_(oldproc, hwnd, msg, wparam, lparam)
  Else
    ProcedureReturn result
  EndIf
 
EndProcedure

Procedure MonitorButtons(hwnd)
  Repeat
    GetWindowRect_(hwnd, @wr.RECT)
    GetCursorPos_(@cp.POINT)
    ; if the cursor is outside the window, the CloseButton
    ; must show normal. All other cases are covered in the callback.
    If Not PtInRect_(wr, cp)
      If gCloseButton_State <> CB_Normal
        gCloseButton_State = CB_Normal
        SendMessage_(hwnd, #WM_NCPAINT, 0,0)
      EndIf
    EndIf
    Delay(15)
  ForEver
EndProcedure

Procedure cb(hwnd, msg, wparam, lparam)
  result = #PB_ProcessPureBasicEvents

  ProcedureReturn result
EndProcedure

OpenWindow(0,0,0,320,240,"Ownerdrawn Frame",#PB_Window_SizeGadget|#PB_Window_ScreenCentered)
CreateGadgetList(WindowID(0))
TextGadget(0,0,0,150,20,"")
SetGadgetColor(0,#PB_Gadget_BackColor, #White)
SetWindowColor(0, #White)
SetProp_(WindowID(0), "oldproc", SetWindowLong_(WindowID(0), #GWL_WNDPROC, @WindowProc()))
CreateStatusBar(0, WindowID(0))

; dry-fire the WM_NCCALCSIZE and WM_NCPAINT events:
SetWindowPos_(WindowID(0),0,0,0,0,0,#SWP_NOMOVE|#SWP_NOSIZE|#SWP_NOZORDER|#SWP_FRAMECHANGED)

; a thread ensures no mistakes in resetting the CloseButton image to normal
CreateThread(@MonitorButtons(), WindowID(0))

ProcessHandle = OpenProcess_(#PROCESS_ALL_ACCESS,#False,GetCurrentProcessId_());

lastgdicount = 0
Repeat
  ev = WaitWindowEvent()
  gdicount = GetGuiResources_(ProcessHandle, 0) ; 0 = #GR_GDIOBJECTS
  If gdicount <> lastgdicount
    lastgdicount = gdicount
    SetGadgetText(0,"GDI Object Count: "+Str(gdicount))
  EndIf
Until ev=#PB_Event_CloseWindow

DeleteObject_(hBrush)

DataSection
  backbrush:         IncludeBinary #PB_Compiler_Home+"Examples\Sources\Data\Background.bmp"
  closebuttons:     
  Data.b $4A,$43,$C0,$0B,$00,$00,$72,$EC,$2F,$DE,$BC,$A9,$D0,$20,$69,$14,$59,$08,$18,$CA
  Data.b $08,$B0,$01,$25,$89,$22,$3C,$06,$18,$23,$98,$C4,$40,$50,$FF,$14,$60,$12,$79,$E2
  Data.b $7C,$80,$D2,$15,$A3,$B1,$CC,$74,$4E,$A2,$C0,$48,$30,$0D,$FD,$EF,$04,$6E,$65,$03
  Data.b $D0,$8C,$F4,$5C,$2E,$D4,$60,$15,$F5,$96,$27,$65,$63,$9D,$36,$AD,$9E,$F5,$57,$29
  Data.b $C7,$AD,$00,$2B,$53,$E3,$81,$15,$5D,$18,$14,$42,$1B,$50,$01,$C0,$58,$27,$67,$FB
  Data.b $04,$7A,$6A,$EC,$A1,$59,$4F,$42,$1B,$E0,$D0,$09,$84,$60,$6C,$B2,$63,$B5,$A3,$4F
  Data.b $99,$77,$19,$A0,$69,$F2,$27,$50,$45,$4E,$8A,$8D,$D5,$42,$B6,$D3,$F3,$ED,$77,$DC
  Data.b $19,$E8,$45,$7D,$6E,$4A,$A0,$3F,$E7,$36,$97,$60,$FE,$1F,$42,$21,$B4,$81,$91,$5A
  Data.b $2D,$74,$5B,$A1,$23,$A7,$55,$CA,$ED,$A4,$C7,$CA,$15,$B9,$60,$59,$BB,$2E,$09,$85
  Data.b $40,$3D,$CF,$9B,$B5,$D0,$27,$FA,$92,$B6,$E8,$4E,$A5,$32,$E2,$1D,$6C,$55,$66,$1D
  Data.b $4F,$96,$59,$AD,$E6,$CD,$E9,$06,$AC,$FC,$82,$F8,$B2,$58,$B4,$65,$2D,$74,$A7,$E2
  Data.b $64,$2E,$3F,$ED,$CB,$D6,$4C,$41,$1D,$F9,$93,$A6,$EC,$F6,$C0,$46,$53,$92,$10,$DA
  Data.b $C0,$6B,$B3,$16,$3A,$A1,$42,$6A,$CC,$90,$D7,$D5,$3E,$91,$52,$B3,$D2,$87,$CE,$2B
  Data.b $97,$E4,$95,$F9,$D3,$AA,$24,$D0,$61,$1A,$4C,$EB,$D7,$E7,$0A,$7A,$80,$07,$A1,$10
  Data.b $DA,$A0,$79,$94,$16,$3C,$44,$7F,$AE,$EE,$DE,$AC,$56,$E1,$C5,$87,$B5,$5A,$EA,$79
  Data.b $B4,$5B,$3E,$45,$0F,$56,$A7,$9D,$50,$BA,$02,$6F,$C0,$D2,$97,$C0,$4E,$AD,$D6,$42
  Data.b $27,$9C,$13,$E1,$43,$7D,$59,$B0,$71,$A5,$40,$23,$FE,$BF,$99,$19,$8B,$3E,$71,$4C
  Data.b $91,$3D,$74,$67,$F6,$7F,$7C,$C0,$34,$5F,$0D,$AA,$A0,$07,$A1,$13,$0A,$A1,$F1,$A5
  Data.b $44,$6B,$56,$1C,$90,$DA,$8E,$B5,$AB,$89,$D2,$A5,$5E,$6D,$BD,$BD,$ED,$DB,$B9,$CE
  Data.b $A7,$5E,$AD,$5F,$35,$59,$80,$0D,$D8,$F4,$B4,$41,$15,$F4,$2D,$74,$42,$21,$C7,$48
  Data.b $CD,$68,$DD,$AA,$7E,$6D,$B2,$55,$D1,$9F,$EF,$DB,$F6,$FB,$FA,$B1,$53,$CF,$B5,$3D
  Data.b $5B,$AE,$80,$B9,$77,$EB,$54,$41,$0F,$D8,$27,$14,$42,$1B,$2A,$A9,$D5,$42,$79,$8D
  Data.b $23,$15,$99,$EF,$7F,$C8,$A1,$BC,$97,$12,$C7,$CD,$52,$4E,$01,$53,$D0,$87,$32,$93
  Data.b $68,$97,$A0,$07,$78,$C0,$0A,$A1,$0D,$AA,$43,$6B,$A1,$13,$D6,$22,$B5,$A4,$5F,$72
  Data.b $07,$4B,$B8,$F0,$C4,$30,$09,$00,$33,$8A,$69,$F6,$25,$D9,$AE,$60,$AB,$B3,$81,$12
  Data.b $70,$00,$68,$83,$2A,$E8,$52,$EB,$84,$42,$1A,$0A,$F1,$24,$86,$55,$AF,$16,$CD,$9D
  Data.b $F8,$E5,$9C,$A3,$3C,$F4,$FF,$EE,$DA,$D0,$85,$DF,$D6,$2B,$00,$F1,$DD,$7E,$D0,$03
  Data.b $25,$D0,$85,$D0,$06,$55,$6A,$B5,$D0,$09,$E3,$47,$83,$4A,$EF,$FF,$C4,$1C,$52,$94
  Data.b $22,$19,$FB,$3E,$8E,$5A,$EF,$BD,$10,$98,$1F,$7E,$4B,$19,$00,$C4,$70,$FD,$E8,$81
  Data.b $12,$70,$42,$68,$83,$02,$B6,$5A,$E8,$84,$C4,$4E,$7D,$B8,$DD,$6B,$58,$D6,$96,$F2
  Data.b $95,$72,$61,$7E,$27,$5B,$F8,$70,$BC,$32,$EC,$99,$80,$9C,$AB,$D7,$FA,$1F,$09,$34
  Data.b $80,$85,$41,$15,$F4,$40,$74,$42,$21,$B4,$D6,$5C,$5B,$2D,$31,$BC,$28,$50,$AE,$58
  Data.b $F9,$E8,$AF,$D7,$2C,$65,$39,$C6,$D9,$C9,$EC,$C6,$01,$A3,$B8,$60,$C1,$34,$D3,$34
  Data.b $00,$FD,$1B,$30,$F7,$50,$42,$27,$14,$42,$87,$B3,$47,$D5,$6D,$71,$A3,$40,$BF,$ED
  Data.b $2F,$D8,$E2,$B8,$FC,$09,$E6,$39,$34,$3F,$E5,$C1,$93,$43,$C2,$6F,$EF,$84,$FF,$7F
  Data.b $D5,$52,$80,$12,$68,$00,$68,$83,$2A,$28,$5A,$E8,$84,$42,$44,$A2,$BC,$B6,$CD,$2E
  Data.b $91,$D4,$CA,$6E,$97,$90,$B4,$6A,$BB,$4B,$36,$13,$A6,$F9,$2F,$49,$EE,$A7,$0F,$B5
  Data.b $06,$98,$84,$36,$A0,$02,$AD,$85,$4E,$28,$E5,$18,$A9,$19,$BC,$67,$EB,$DF,$CF,$17
  Data.b $AD,$FD,$FF,$03,$B3,$C5,$F4,$8B,$75,$6A,$D4,$1A,$80,$3F,$42,$68,$03,$2B,$7D,$5A
  Data.b $E8,$84,$A4,$56,$F4,$27,$B6,$3F,$8C,$46,$76,$4B,$09,$DC,$3A,$CC,$A9,$01,$1F,$EB
  Data.b $84,$84,$D7,$86,$E0,$CA,$00,$FD,$A5,$2F,$C0,$03,$DA,$D0,$85,$D0,$06,$55,$6A,$B5
  Data.b $D0,$09,$4E,$76,$2C,$45,$DE,$CD,$96,$E5,$D9,$F0,$68,$27,$36,$ED,$77,$CA,$7A,$AF
  Data.b $A7,$A6,$FE,$DB,$46,$7D,$07,$4A,$E0,$00,$A1,$0D,$AA,$A0,$6B,$A1,$13,$0A,$B8,$C1
  Data.b $0C,$46,$5F,$EF,$D9,$E1,$F5,$F7,$45,$7B,$06,$28,$C0,$69,$B6,$76,$BF,$5F,$9C,$F3
  Data.b $27,$8C,$BD,$4F,$C3,$96,$40,$09,$60,$63,$B3,$41,$15,$F4,$FF,$BF,$69,$F3,$16,$F6
  Data.b $73,$02,$28,$71,$48,$AD,$BF,$69,$19,$00,$9A,$01,$AD,$7E,$D0,$C0,$80,$01,$3D,$FF
  Data.b $0B,$66,$F4,$00,$67,$63,$21,$B8,$41,$15,$5A,$2D,$74,$02,$48,$A1,$E2,$90,$B6,$6C
  Data.b $EB,$9F,$3E,$2D,$80,$76,$05,$BF,$76,$12,$58,$8D,$03,$A0,$93,$1A,$30,$94,$50,$05
  Data.b $3D,$40,$9D,$50,$08,$6D,$31,$3B,$55,$0B,$0F,$66,$8B,$9B,$FC,$05,$53,$FE,$66,$A1
  Data.b $37,$B5,$B9,$59,$FE,$BD,$40,$05,$3D,$40,$C7,$7E,$C1,$78,$9F,$13,$FA,$43,$19,$6A
  Data.b $B5,$F0,$4B,$DA,$E6,$A9,$AE,$ED,$D2,$E1,$29,$8B,$01,$14,$EF,$86,$E5,$4F,$00,$65
  Data.b $63,$F7,$E1,$6C,$15,$F4,$68,$C1,$13,$0E,$89,$D4,$DC,$A3,$F1,$90,$50,$AE,$09,$65
  Data.b $AD,$5A,$E3,$38,$00,$DB,$F7,$DE,$1D,$43,$9A,$75,$32,$E8,$81,$06,$D0,$ED,$AB,$82
  Data.b $1E,$28,$16,$3A,$01,$0F,$35,$7B,$54,$87,$52,$C4,$D9,$A1,$FC,$D6,$BF,$D9,$D4,$FE
  Data.b $0C,$10,$41,$DE,$BB,$4B,$38,$6B,$DA,$A2,$6C,$E0,$1A,$20,$0D,$AA,$80,$07,$B2,$A5
  Data.b $1E,$A0,$62,$FD,$CC,$0D,$7A,$21,$BC,$2C,$AC,$E6,$C2,$00,$D5,$9D,$42,$B7,$19,$6A
  Data.b $13,$A1,$0F,$6C,$03,$85,$42,$1B,$54,$41,$D5,$42,$27,$14,$80,$92,$1A,$A9,$E0,$6D
  Data.b $DB,$FA,$19,$F2,$70,$19,$4B,$B8,$53,$2A,$FE,$3B,$16,$F0,$3C,$73,$12,$07,$12,$68
  Data.b $00,$C4,$83,$2A,$E8,$81,$E8,$84,$42,$68,$41,$25,$B5,$5A,$0A,$EB,$6F,$41,$FF,$86
  Data.b $E1,$52,$66,$94,$C1,$1A,$E4,$BD,$8D,$B3,$F0,$99,$E8,$D1,$71,$56,$02,$0D,$42,$21
  Data.b $B4,$01,$91,$5A,$2D,$74,$21,$35,$8E,$28,$EF,$96,$8D,$4F,$4A,$DD,$B1,$F4,$D4,$DF
  Data.b $BB,$76,$55,$EE,$FB,$B8,$00,$9B,$7D,$06,$D0,$03,$25,$D0,$85,$D0,$06,$55,$6A,$B5
  Data.b $D0,$09,$B7,$AE,$2F,$4C,$B9,$14,$F3,$9C,$BC,$D9,$B1,$94,$D7,$00,$FF,$7D,$E6,$71
  Data.b $49,$70,$C6,$DD,$8B,$93,$D0,$00,$ED,$ED,$55,$D0,$03,$25,$09,$85,$D0,$06,$4F,$A4
  Data.b $B5,$D0,$CF,$13,$CB,$B5,$5F,$F1,$87,$0C,$9D,$42,$25,$E5,$71,$6D,$30,$EF,$1C,$BA
  Data.b $FC,$F7,$C7,$74,$21,$FF,$09,$34,$00,$7F,$BB,$E5,$F5,$40,$7F,$CF,$52,$CE,$5A,$E8
  Data.b $04,$FF,$9E,$4F,$FC,$AD,$B3,$FD,$4A,$B2,$7B,$B1,$53,$DB,$FB,$FF,$5D,$FB,$9A,$3E
  Data.b $AD,$D3,$3F,$77,$2C,$E3,$2B,$81,$06,$D0,$A1,$0D,$EC,$D8,$6A,$A1,$13,$0A,$14,$52
  Data.b $F3,$DA,$E7,$BE,$0E,$AA,$29,$74,$39,$77,$7D,$DD,$B8,$E8,$CD,$5C,$92,$FA,$3C,$71
  Data.b $DB,$BE,$38,$B0,$5F,$A1,$07,$F3,$9D,$9F,$F4,$84,$29,$EA,$27,$7D,$C4,$9A,$2A,$F0
  Data.b $1B,$94,$21,$B4,$41,$6E,$3D,$2D,$74,$42,$22,$D4,$0F,$2B,$12,$46,$55,$BC,$CC,$97
  Data.b $01,$F4,$FE,$01,$C9,$92,$4E,$64,$FB,$AE,$86,$37,$48,$99,$66,$C1,$9D,$D1,$38,$6C
  Data.b $87,$95,$2A,$E8,$01,$12,$5B,$FD,$35,$EC,$82,$27,$54,$E6,$D3,$38,$33,$D4,$CD,$2A
  Data.b $BC,$D2,$B4,$5C,$CF,$97,$FE,$85,$6A,$FA,$4B,$47,$AD,$1A,$CF,$E0,$BC,$89,$15,$DB
  Data.b $F8,$A6,$B8,$60,$F5,$D7,$09,$34,$00,$7C,$41,$15,$F4,$40,$74,$42,$21,$B4,$6A,$5C
  Data.b $5B,$2D,$BD,$5F,$BB,$4C,$BB,$0F,$CC,$F7,$53,$FF,$93,$15,$DD,$D9,$39,$6B,$D5,$97
  Data.b $F7,$1E,$7F,$9A,$32,$7D,$EE,$49,$4B,$66,$4F,$56,$8F,$01,$A9,$2F,$5F,$4A,$17,$E9
  Data.b $CE,$FA,$50,$08,$6D,$80,$EA,$53,$0B,$9D,$4F,$3A,$94,$3D,$FF,$9C,$07,$17,$37,$33
  Data.b $80,$E1,$B3,$61,$29,$B4,$DC,$94,$69,$EB,$6B,$7E,$63,$76,$17,$FF,$BA,$2F,$97,$CA
  Data.b $97,$DC,$93,$40,$E6,$FE,$49,$35,$BE,$35,$B4,$01,$63,$A6,$2D,$74,$42,$21,$4B,$89
  Data.b $36,$43,$7C,$C2,$73,$29,$B5,$FB,$54,$8B,$67,$BA,$07,$4B,$23,$CA,$CF,$2C,$97,$BD
  Data.b $5A,$78,$EB,$3B,$55,$E9,$31,$62,$CF,$00,$50,$05,$3D,$A0,$9D,$50,$08,$6D,$37,$35
  Data.b $5A,$0B,$FA,$84,$D4,$90,$E4,$C1,$BE,$93,$0C,$05,$78,$3F,$E7,$73,$76,$0C,$F4,$7F
  Data.b $DD,$A2,$DD,$99,$02,$FC,$4F,$03,$C0,$AF,$31,$20,$3E,$ED,$A8,$3B,$46,$EF,$B4,$C1
  Data.b $FF,$E0,$2D,$74,$42,$21,$F4,$6D,$74,$67,$5E,$D3,$A3,$DE,$69,$E1,$B4,$1E,$E9,$AA
  Data.b $29,$B8,$CA,$F5,$D6,$14,$21,$21,$79,$68,$01,$14,$FF,$C8,$32,$1A,$02,$8D,$EB,$AA
  Data.b $7D,$E0,$84,$42,$70,$83,$EA,$CD,$5A,$E8,$1F,$85,$69,$5D,$79,$BE,$77,$9D,$9E,$9F
  Data.b $7A,$71,$CE,$F4,$89,$67,$F9,$67,$84,$2C,$2F,$5C,$33,$45,$86,$9F,$D2,$C9,$05,$3D
  Data.b $60,$03,$50,$08,$6D,$50,$9D,$59,$0B,$9D,$60,$E8,$9E,$27,$67,$3F,$6B,$95,$AF,$33
  Data.b $AE,$33,$79,$DC,$FD,$3D,$2F,$5F,$7B,$BF,$B8,$90,$A7,$F0,$6C,$60,$9A,$07,$D0,$06
  Data.b $94,$F2,$B5,$D0,$09,$85,$A2,$5B,$66,$74,$E8,$28,$EB,$8D,$CD,$E8,$A8,$C0,$8A,$6E
  Data.b $B4,$DE,$E8,$CD,$06,$70,$BF,$75,$EB,$9C,$F4,$BC,$71,$AB,$49,$BA,$5D,$CB,$3A,$A1
  Data.b $10,$BC,$6E,$F7,$BF,$16,$0D,$75,$A8,$45,$CA,$A6,$50,$FD,$33,$60,$53,$AB,$81,$69
  Data.b $8C,$62,$14,$82,$09,$B8,$BD,$AB,$5D,$27,$53,$25,$03,$E6,$6D,$DE,$4C,$CE,$B0,$27
  Data.b $9C,$BC,$18,$EB,$84,$42,$88,$44,$08,$00,$00,$00,$00,$00
  closebuttonsend:
EndDataSection 
Post Reply