Draw Rectangle or Ellipse on Desktop
Posted: Thu Dec 29, 2022 4:13 pm
As the title, Draw a Rectangle or an Ellipse on Desktop, Area Requester for Windows only
Code: Select all
;- Top
; -----------------------------------------------------------------------------
; Name: DrawRectEllipseOnDesktop.pb
; Description: Draw a Rectangle or an Ellipse on Desktop (Use Esc or Right Click to exit), Area Requester.
; Author: ChrisR
; Date: 2022-12-29
; OS: Windows Only, DPIaware
; Note: For the test here, the rectangle is drawn first and then on closing the ellipse is drawn (Look for "TEST" label)
; -----------------------------------------------------------------------------
EnableExplicit
Enumeration Window
#WinDesktop
EndEnumeration
Enumeration Image
#ImgDesktop
EndEnumeration
Enumeration Shortcut
#Shortcut_Escape = 3
EndEnumeration
Global MaxW, MaxH
Global Dim Handle.Rect(5)
Global HSize = DesktopScaledX(16) ; Image Handle Size 16,12,...
Global Ellipse ; DrawRectangle -> Ellipse=#False, DrawEllipse -> Ellipse=#True
Macro InitSize()
Handle(0)\left = MaxW /4 : Handle(0)\top = MaxH /4 : Handle(0)\right = MaxW * 3/4 : Handle(0)\bottom = MaxH * 3/4
EndMacro
Macro DrawHandle()
ImgRect = CreateImage(#PB_Any, HSize, HSize, 32, RGBA(0,0,25,255))
ImgRectID = ImageID(ImgRect)
If StartDrawing(ImageOutput(ImgRect)) ; For Background Transparency
DrawingMode(#PB_2DDrawing_AlphaChannel)
Box(2, 2, HSize-4, HSize-4, RGBA(0,0,0,1))
StopDrawing()
EndIf
EndMacro
Procedure GetDesktopSize()
Protected WinTemp.i
WinTemp = OpenWindow(#PB_Any, 0, 0, 1, 1, "", #PB_Window_Invisible | #PB_Window_BorderLess | #PB_Window_Maximize)
MaxW = DesktopScaledX(WindowWidth(WinTemp))
MaxH = DesktopScaledY(WindowHeight(WinTemp))
CloseWindow(WinTemp)
EndProcedure
Procedure UpdateLayeredWindow(hDC)
Protected sz.SIZE, BlendMode.BLENDFUNCTION, ContextOffset.POINT
; hDC = StartDrawing(ImageOutput(#ImgDesktop)) ; Already done in DrawRectangle()
With sz.SIZE
\cx = ImageWidth(#ImgDesktop)
\cy = ImageHeight(#ImgDesktop)
EndWith
With BlendMode.BLENDFUNCTION
\SourceConstantAlpha = 255
\AlphaFormat = 1
EndWith
UpdateLayeredWindow_(WindowID(#WinDesktop), 0, 0, @sz, hDC, @ContextOffset.POINT, 0, @BlendMode, 2)
; StopDrawing() ; Already done in DrawRectangle()
EndProcedure
Procedure CalcHandlePos()
Protected Width, Height, MHSize = HSize/2
With Handle(0)
Width = \right - \left : Height = \bottom - \top
; Handle Position
Handle(1)\left = \left -MHSize : Handle(1)\top = \top -MHSize : Handle(1)\right = \left +MHSize : Handle(1)\bottom = \top +MHSize
Handle(2)\left = \right -MHSize : Handle(2)\top = \top -MHSize : Handle(2)\right = \right +MHSize : Handle(2)\bottom = \top +MHSize
Handle(3)\left = \right -MHSize : Handle(3)\top = \bottom -MHSize : Handle(3)\right = \right +MHSize : Handle(3)\bottom = \bottom +MHSize
Handle(4)\left = \left -MHSize : Handle(4)\top = \bottom -MHSize : Handle(4)\right = \left +MHSize : Handle(4)\bottom = \bottom +MHSize
; Middle, center Handle
Handle(5)\left = \Left + Width/2 -MHSize : Handle(5)\top = \top + Height/2 -MHSize : Handle(5)\right = \Left + Width/2 +MHSize : Handle(5)\bottom = \top + Height/2 +MHSize
EndWith
EndProcedure
Procedure DrawEllipse()
Protected hDC, ImgRect, RadiusX, RadiusY, I
Static ImgRectID
Ellipse = #True
If Not ImgRectID : DrawHandle() : EndIf
CalcHandlePos()
RadiusX = (Handle(0)\right - Handle(0)\left)/2 : RadiusY = (Handle(0)\bottom - Handle(0)\top)/2
CreateImage(#ImgDesktop, MaxW, MaxH, 32, #PB_Image_Transparent)
hDC = StartDrawing(ImageOutput(#ImgDesktop))
If hDC
DrawingMode(#PB_2DDrawing_Outlined | #PB_2DDrawing_AllChannels)
Ellipse(Handle(0)\left + RadiusX, Handle(0)\top + RadiusY, Abs(RadiusX), Abs(RadiusY), RGBA(0,0,25,255))
DrawingMode(#PB_2DDrawing_AllChannels)
For I = 1 To 5
DrawImage(ImgRectID, Handle(I)\left, Handle(I)\top)
Next
UpdateLayeredWindow(hDC)
StopDrawing()
EndIf
EndProcedure
Procedure DrawRectangle()
Protected hDC, ImgRect, I
Static ImgRectID
Ellipse = #False
If Not ImgRectID : DrawHandle() : EndIf
CalcHandlePos()
CreateImage(#ImgDesktop, MaxW, MaxH, 32, #PB_Image_Transparent)
hDC = StartDrawing(ImageOutput(#ImgDesktop))
If hDC
DrawingMode(#PB_2DDrawing_Outlined | #PB_2DDrawing_AllChannels)
Box(Handle(0)\left, Handle(0)\top, Handle(0)\right - Handle(0)\left, Handle(0)\bottom - Handle(0)\top, RGBA(0,0,25,255))
DrawingMode(#PB_2DDrawing_AllChannels)
For I = 1 To 5
DrawImage(ImgRectID, Handle(I)\left, Handle(I)\top)
Next
UpdateLayeredWindow(hDC)
StopDrawing()
EndIf
EndProcedure
;- Main
Define EventID, Drag, MouseX, MouseX0, MouseY, MouseY0, DragX, DragY, ID
GetDesktopSize()
OpenWindow(#WinDesktop, 0, 0, MaxW, MaxH, "", #PB_Window_BorderLess | #PB_Window_ScreenCentered)
SetWindowLongPtr_(WindowID(#WinDesktop), #GWL_EXSTYLE, GetWindowLongPtr_(WindowID(#WinDesktop), #GWL_EXSTYLE) | #WS_EX_LAYERED)
StickyWindow(#WinDesktop, #True)
CreatePopupMenu(0)
MenuItem(#Shortcut_Escape, "Exit")
AddKeyboardShortcut(#WinDesktop, #PB_Shortcut_Escape, #Shortcut_Escape)
InitSize()
DrawRectangle()
;DrawEllipse()
Repeat
If Drag
If Not (GetKeyState_(#VK_LBUTTON) & 32768)
Drag = #False
EndIf
MouseX = DesktopMouseX()
MouseY = DesktopMouseY()
If MouseX <> MouseX0 Or MouseY <> MouseY0
DragX = MouseX - MouseX0 : DragY = MouseY - MouseY0
MouseX0 = MouseX : MouseY0 = MouseY
With Handle(0)
Select ID
Case 1
\left + DragX : \top + DragY
Case 2
\top + DragY : \right + DragX
Case 3
\right + DragX : \bottom + DragY
Case 4
\left + DragX : \bottom + DragY
Case 5 ; Move
If \left + DragX >= 0 And \left + DragX <= MaxW And \right + DragX >= 0 And \right + DragX <= MaxW
\left + DragX : \right + DragX
EndIf
If \top + DragY >= 0 And \top + DragY <= MaxH And \bottom + DragY >= 0 And \bottom + DragY <= MaxH
\top + DragY : \bottom + DragY
EndIf
EndSelect
EndWith
If Ellipse
DrawEllipse()
Else
DrawRectangle()
EndIf
EndIf
EndIf
EventID = WaitWindowEvent(1)
Select EventID
Case #WM_LBUTTONDOWN
MouseX0 = DesktopMouseX()
MouseY0 = DesktopMouseY()
For ID = 1 To 5
If MouseX0 >= Handle(ID)\left And MouseY0 >= Handle(ID)\top And MouseX0 <= Handle(ID)\right And MouseY0 <= Handle(ID)\bottom
Drag = #True
Break
EndIf
Next
;SendMessage_(WindowID(#WinDesktop), #WM_NCLBUTTONDOWN, #HTCAPTION, 0) ; Move the image by following mouse movements
Case #WM_LBUTTONUP
Drag = #False
Case #PB_Event_Menu
If EventMenu() = #Shortcut_Escape
With Handle(0)
Debug "Left: " + Str(\left) + " - Top: " + Str(\top) + " - Right: " + Str(\right) + " - Bottom: " + Str(\bottom) + " - (Play with Min, Max if needed)"
EndWith
; TEST: Draw Rectangle then Ellipse. Not to do, remove the If-Endif block and replace it by Break only
If Ellipse = #False
InitSize()
DrawEllipse()
Else
Break
EndIf
EndIf
Case #WM_RBUTTONDOWN
DisplayPopupMenu(0, WindowID(#WinDesktop))
EndSelect
Until EventID = #PB_Event_CloseWindow