Sign in to follow this  
Followers 0
siva1612

Creating a smooth round control

2 posts in this topic

#1 ·  Posted

I'm trying to create a round control, preferably a label.

The control appears in a child window which has to be frequently hidden and shown alternatively.

The controls also overlaps on other label controls and has to recognize a click event.

The things I've tried and the drawbacks of them are listed below.

1. I created a circular hole in the child window with a label in the background main window. This meets all my requirements but the resulting hole is not smooth. Any way to  make it smooth?

#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <WinAPI.au3>

Opt("GUIOnEventMode", 1)

$MainScreen = GUICreate("Expense Tracker", 600, 520, -1, -1, -1)
GUISetOnEvent($GUI_EVENT_CLOSE, "ExitAll")

$ClickLbl = GUICtrlCreateLabel("", 120, 400, 60, 60)
GUICtrlSetBkColor(-1, 0x2DB84C)

GUISetState(@SW_SHOW, $MainScreen)


$LeftFrameScr = GUICreate("", 300, 450, 0, 30, $WS_POPUP, $WS_EX_MDICHILD, $MainScreen)
GUISetBkColor(0xFF00FF)
GUISetFont(11, 500, 0, "Calibri")

$hFullRgn = _WinAPI_CreateRectRgn(0, 0, 300, 450)
$hRoundRgn = _WinAPI_CreateRoundRectRgn(120, 370, 180, 430, 60, 60)
$hCombined_rgn = _WinAPI_CreateRectRgn(0, 0, 0, 0)

_WinAPI_CombineRgn($hCombined_rgn, $hFullRgn, $hRoundRgn, $RGN_DIFF)
_WinAPI_SetWindowRgn($LeftFrameScr, $hCombined_rgn)

_WinAPI_DeleteObject($hFullRgn)
_WinAPI_DeleteObject($hRoundRgn)


GUISetState(@SW_SHOW, $LeftFrameScr)

While 1

WEnd

Func ExitAll()
    Exit
EndFunc   ;==>ExitAll

2. I created the control using GDI+ directly in the window or in a graphic control. This created a smooth circle, but the control disappears every time I hide and reopen the window. Also, if I use this method, the event for the control below the graphic control will not be triggered.

#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <WinAPI.au3>
#include <GDIPlus.au3>
#include <Array.au3>

Opt("GUIOnEventMode", 1)

Global $hGraphics, $hBrush

$MainScreen = GUICreate("Expense Tracker", 600, 520, -1, -1, -1)
GUISetOnEvent($GUI_EVENT_CLOSE, "ExitAll")

_GDIPlus_Startup()

GUISetState(@SW_SHOW, $MainScreen)

$LeftFrameScr = GUICreate("", 300, 450, 0, 30, $WS_POPUP, $WS_EX_MDICHILD, $MainScreen)
GUISetBkColor(0xFF00FF)
GUISetFont(11, 500, 0, "Calibri")

$AddButton = GUICtrlCreateGraphic(120, 370, 60, 60)
GUICtrlSetBkColor(-1, 0xFFFFFF);$GUI_BKCOLOR_TRANSPARENT)

GUISetState(@SW_SHOW, $LeftFrameScr)
CreateAddButton($LeftFrameScr, $AddButton)

Sleep(2000)
GUISetState(@SW_HIDE, $LeftFrameScr)
Sleep(500)
GUISetState(@SW_SHOW, $LeftFrameScr)

While 1

WEnd

Func ExitAll()
    _GDIPlus_BrushDispose($hBrush)
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_Shutdown()
    Exit
EndFunc   ;==>ExitAll

Func CreateAddButton($ParentWndw, $GraphicsControl)
    $CtrlPos = ControlGetPos($ParentWndw, "", $GraphicsControl)

    $hGraphics = _GDIPlus_GraphicsCreateFromHWND(GUICtrlGetHandle($GraphicsControl))
    $hBrush = _GDIPlus_BrushCreateSolid(0xFF2DB84C)
    _GDIPlus_GraphicsSetSmoothingMode($hGraphics, 2)
    _GDIPlus_GraphicsFillEllipse($hGraphics, 0, 0, $CtrlPos[2] - 1, $CtrlPos[3] - 1, $hBrush)
    $hPen = _GDIPlus_PenCreate(0xFFFFFFFF, 2)
EndFunc

 

Share this post


Link to post
Share on other sites



#2 ·  Posted

This GDI+ method works.

#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>

;Opt('MustDeclareVars', 1)
Opt("MouseCoordMode", 2) ;1=absolute, 0=relative, 2=client

Global $hGUI, $hBMPBuff, $hGraphicGUI, $hGraphic

_Main()

Func _Main()
    Local $msg, $aPos, $GuiSizeX = 400, $GuiSizeY = 300
    Local $hButton
    ; Create GUI
    $hGUI = GUICreate("GDI+", $GuiSizeX, $GuiSizeY)

    _GDIPlus_Startup()
    $hGraphicGUI = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    $hBMPBuff = _GDIPlus_BitmapCreateFromGraphics($GuiSizeX, $GuiSizeY, $hGraphicGUI)
    $hGraphic = _GDIPlus_ImageGetGraphicsContext($hBMPBuff)
    _GDIPlus_GraphicsClear($hGraphic, 0xFFFFFFDD)

    ; Create coloured circle.
    Local $hPen = _GDIPlus_PenCreate(0xFF0000FF, 2)
    Local $hBrush = _GDIPlus_BrushCreateSolid(0xFFE0A0FF)
    Local $iElpsX = 50, $iElpsY = 30, $iElpsWidth = 40, $iElpsHth = 40
    _GDIPlus_GraphicsSetSmoothingMode($hGraphic, 1)
    _GDIPlus_GraphicsDrawEllipse($hGraphic, $iElpsX, $iElpsY, $iElpsWidth, $iElpsHth, $hPen) ; Border
    _GDIPlus_GraphicsFillEllipse($hGraphic, $iElpsX, $iElpsY, $iElpsWidth, $iElpsHth, $hBrush) ; Fill

    ; Repainted on PAINT-Events
    GUIRegisterMsg(0xF, "MY_PAINT") ; Register PAINT-Event 0x000F = $WM_PAINT (WindowsConstants.au3)
    GUIRegisterMsg(0x85, "MY_PAINT") ; $WM_NCPAINT = 0x0085 (WindowsConstants.au3)Restore after Minimize.
    _GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)

    GUISetState()

    While 1
        $msg = GUIGetMsg()
        Switch $msg
            Case $GUI_EVENT_CLOSE
                _GDIPlus_GraphicsDispose($hGraphic)
                _GDIPlus_GraphicsDispose($hGraphicGUI)
                _WinAPI_DeleteObject($hBMPBuff)
                _GDIPlus_Shutdown()
                Exit
            Case $GUI_EVENT_PRIMARYUP
                $aPos = MouseGetPos()
                Select
                    Case _PointInEllipse($aPos[0], $aPos[1], $iElpsX, $iElpsY, $iElpsWidth, $iElpsHth)
                        MsgBox(0, "", "Clicked in Circle", 4, $hGUI)
                EndSelect
        EndSwitch
    WEnd
EndFunc   ;==>_Main


; ------------ _PointInEllipse --------------------------
; ($xPt, $yPt) - x, y position of the point to check
;  $xTL, $yTL,  Top left x Pos, top left Y position of the rectangle encompassing the ellipse.
; $w, $h - The width an height of ellipse
; Ref  http://www.autoitscript.com/forum/index.php?showtopic=89034&view=findpost&p=639786
;
Func _PointInEllipse($xPt, $yPt, $xTL, $yTL, $w, $h)
    Local $bInside = False, $a = $w / 2, $b = $h / 2
    Local $c1X, $c2X, $dist, $xc = $xTL + $a, $yc = $yTL + $b
    $c1X = $xc - ($a ^ 2 - $b ^ 2) ^ (1 / 2) ; 1st focal point x position
    $c2X = $xc + ($a ^ 2 - $b ^ 2) ^ (1 / 2) ; 2nd focal point x position
    $dist = (($xPt - $c1X) ^ 2 + ($yPt - $yc) ^ 2) ^ 0.5 + (($xPt - $c2X) ^ 2 + ($yPt - $yc) ^ 2) ^ 0.5
    If $dist <= $w Then $bInside = Not $bInside
    Return $bInside
EndFunc   ;==>_PointInEllipse

;Func to redraw on PAINT MSG
Func MY_PAINT($hWnd, $msg, $wParam, $lParam)
    ; Check, if the GUI with the Graphic should be repainted
    _GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)
    _WinAPI_RedrawWindow($hGUI, "", "", BitOR($RDW_INVALIDATE, $RDW_UPDATENOW, $RDW_FRAME)) ;,$RDW_ALLCHILDREN
    Return $GUI_RUNDEFMSG
EndFunc   ;==>MY_PAINT

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0