WildByDesign Posted 10 hours ago Posted 10 hours ago My GDI+ skills are next to zero and therefore I need some help with adding a curve/arc to an existing line, please. I know that there are lots of curve/arc functions related to GDI+ path and drawing but I have not been successful with them and don't fully understand. Goal: Draw a simple curve at the top and bottom of a single vertical line. The idea is to represent the end of a button. Why: I am trying to fix a Microsoft bug in their theme engine related to BS_SPLITBUTTON. Part of my fix involves adding new images to the ImageList for these splitbuttons to cover up their bugged dropdown arrow and vertical split. So I am drawing a vertical split and dropdown button of my own. The problem is that, in order to cover up MS bug, my fix unfortunately has to cut off the very end (right side) of the button border and part of the curvature. What I have so far: I just need help with adding a slight curve to the top and bottom. The curve should mimic the curvature from the opposite side of the button. the curve goes in about 3 pixels. Please don't worry about color. Once everything is working, I will have to change the border color and background color to match the existing theme for hover, select, disabled, etc. Thank you! If you need to see what is being covered up, you can briefly comment out the following line (107): _GUICtrlButton_SetSplitInfo($hWnd, $hImage, $BCSS_IMAGE, 32) Here is my current code for this: expandcollapse popup#include "C:\Program Files (x86)\AutoIt3\Examples\Helpfile\Extras\HelpFileInternals.au3" #include "C:\Program Files (x86)\AutoIt3\Examples\Helpfile\Extras\WM_NOTIFY.au3" #include <GuiButton.au3> #include <GUIConstantsEx.au3> #include <GuiMenu.au3> #include <WinAPI.au3> #include <WinAPITheme.au3> #include <StructureConstants.au3> #include <WindowsNotifsConstants.au3> #include <WindowsStylesConstants.au3> #include <GDIPlus.au3> #include <GuiImageList.au3> #include <ButtonConstants.au3> #include <FontConstants.au3> #include <APIGdiConstants.au3> #include <GDIPlusConstants.au3> ;#include "GUIDarkTheme.au3" ; initiate System DPI awareness DllCall("user32.dll", "bool", "SetProcessDpiAwarenessContext", @AutoItX64 ? "int64" : "int", -2) Global $g_hBtn, $g_hBtn2 _GDIPlus_Startup() Example() Func Example() Local $hGUI = GUICreate("Button Set SplitInfo (v" & @AutoItVersion & ")", 600, 400) GUISetBkColor(0x191919) Local $iDpiRatio = Round(_WinAPI_GetDPIForWindow($hGUI) / 96, 2) If @error Then $iDpiRatio = 1 ;Local $iDpiRatio = 1 ConsoleWrite("dpi: " & $iDpiRatio & @CRLF) _MemoCreate(10, 100, 590, 284, $WS_VSCROLL) ;~ $g_hBtn = _GUICtrlButton_Create($hGUI, "Split Button", 10, 10, 120, 30, $BS_SPLITBUTTON) ;~ _GUICtrlButton_SetSplitInfo($g_hBtn) $g_hBtn2 = _GUICtrlButton_Create($hGUI, "Split Button 2", 10, 40, 180, 50, $BS_SPLITBUTTON) ;;; Local $hWnd = $g_hBtn2 _WinAPI_SetWindowTheme($hWnd, "DarkMode_Explorer", "Button") Local $iButtonHeight = _WinAPI_GetWindowHeight($hWnd) ConsoleWrite("button height: " & $iButtonHeight & @CRLF) ;_GUICtrlButton_SetSplitInfo($hWnd, -1, $BCSS_IMAGE) ;_GUICtrlButton_SetSplitInfo($hWnd, -1, $BCSS_STRETCH, 13, 13) Local $aInfo =_GUICtrlButton_GetSplitInfo($hWnd) ConsoleWrite("width: " & $aInfo[2] & @CRLF) ConsoleWrite("height: " & $aInfo[3] & @CRLF) Local $iSizeW = 32 Local $iSizeH = $iButtonHeight - 4 ; button height minus 4 Local $hImage = _GUIImageList_Create($iSizeW, $iSizeH) Local $iW = 32, $iH = $iSizeH Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH) Local $hBmpCtxt = _GDIPlus_ImageGetGraphicsContext($hBitmap) ;get the graphics context of the bitmap _GDIPlus_GraphicsSetSmoothingMode($hBmpCtxt, $GDIP_SMOOTHINGMODE_HIGHQUALITY) _GDIPlus_GraphicsClear($hBmpCtxt, 0xFF333333) ; change later to 333333 Local $hPath = _GDIPlus_PathCreate() _GDIPlus_PathAddLine($hPath, 1, 2, 1, $iH - 3) ; vertical split _GDIPlus_PathCloseFigure($hPath) Local $hPath2 = _GDIPlus_PathCreate() _GDIPlus_PathAddLine($hPath2, $iW - 1, 1, $iW - 1, $iH - 1) ; button border fix <<<< need help with curve here _GDIPlus_PathCloseFigure($hPath2) Local $hPen = _GDIPlus_PenCreate(0xFFa0a0a0, 1) Local $hPen2 = _GDIPlus_PenCreate(0xFF9b9b9b, 1) _GDIPlus_GraphicsDrawPath($hBmpCtxt, $hPath, $hPen) _GDIPlus_GraphicsDrawPath($hBmpCtxt, $hPath2, $hPen2) Local $hDC = _GDIPlus_GraphicsGetDC($hBmpCtxt) Local $hFont = _WinAPI_CreateFont(Round(12 * $iDpiRatio), 0, 0, 0, 400, False, False, False, $DEFAULT_CHARSET, _ $OUT_DEFAULT_PRECIS, $CLIP_DEFAULT_PRECIS, $DEFAULT_QUALITY, 0, 'Segoe MDL2 Assets') Local $hOldFont = _WinAPI_SelectObject($hDC, $hFont) _WinAPI_SetTextColor($hDC, _WinAPI_SwitchColor(0xFFFFFF)) _WinAPI_SetBkMode($hDC, $TRANSPARENT) Local $tRECT = _WinAPI_CreateRectEx(0, 0, $iW, $iH) Local $iTextFlags = BitOR($DT_SINGLELINE, $DT_CENTER, $DT_NOCLIP, $DT_VCENTER) _WinAPI_DrawText($hDC, ChrW(0xEDDC), $tRECT, $iTextFlags) _GDIPlus_GraphicsReleaseDC($hBmpCtxt, $hDC) _WinAPI_SelectObject($hDC, $hOldFont) _WinAPI_DeleteObject($hFont) _GDIPlus_PenDispose($hPen) _GDIPlus_PenDispose($hPen2) _GDIPlus_PathDispose($hPath) _GDIPlus_PathDispose($hPath2) Local $hHBMP = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap) _GUIImageList_Add($hImage, $hHBMP) ; normal _GUIImageList_Add($hImage, $hHBMP) ; hover _GUIImageList_Add($hImage, $hHBMP) ; click _GUIImageList_Add($hImage, $hHBMP) ; disabled _GUIImageList_Add($hImage, $hHBMP) ; focus ;_GUIImageList_Add($hImage, _WinAPI_CreateSolidBitmap($hWnd, 0xFF0000, $iSize, $iSize)) ; normal ;_GUIImageList_Add($hImage, _WinAPI_CreateSolidBitmap($hWnd, 0x00FF00, $iSize, $iSize)) ; hover ;_GUIImageList_Add($hImage, _WinAPI_CreateSolidBitmap($hWnd, 0x0000FF, $iSize, $iSize)) ; click ;_GUIImageList_Add($hImage, _WinAPI_CreateSolidBitmap($hWnd, 0x333333, $iSize, $iSize)) ; disabled ;_GUIImageList_Add($hImage, _WinAPI_CreateSolidBitmap($hWnd, 0x808080, $iSize, $iSize)) ; focus _GUICtrlButton_SetSplitInfo($hWnd, $hImage, $BCSS_IMAGE, 32) ;_GUICtrlButton_SetSplitInfo($hWnd, $hImage, BitOR($BCSS_IMAGE, $BCSS_NOSPLIT)) ; remove split ;_GUICtrlButton_SetSplitInfo($hWnd, -1, $BCSS_NOSPLIT) Local $aInfo =_GUICtrlButton_GetSplitInfo($hWnd) ConsoleWrite("width: " & $aInfo[2] & @CRLF) ConsoleWrite("height: " & $aInfo[3] & @CRLF) ConsoleWrite("imagelist: " & $aInfo[0] & @CRLF) ConsoleWrite("imagelist count custom: " & _GUIImageList_GetImageCount($aInfo[0]) & @CRLF) ;WinSetState($hWnd, "", @SW_DISABLE) ;;; _SendMessage($g_hBtn2, $WM_CHANGEUISTATE, 65537, 0) GUIRegisterMsg($WM_COMMAND, "WM_COMMAND") _WM_NOTIFY_Register($_g_idLst_Memo) ;_GUIDarkTheme_ApplyDark($hGUI) GUISetState(@SW_SHOW) Local $aInfo = _GUICtrlButton_GetSplitInfo($g_hBtn) _MemoWrite("Split Info" & @CRLF & "----------------") For $x = 0 To 3 _MemoWrite("$ainfo[" & $x & "] = " & $aInfo[$x]) Next _MemoWrite("Split Info" & @CRLF & "----------------") While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd _GDIPlus_Shutdown() Exit EndFunc ;==>Example Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg, $wParam Local Const $BCN_HOTITEMCHANGE = -1249 Local $tagNMBHOTITEM = $tagNMHDR & ";dword dwFlags" Local $tNMBHOTITEM = DllStructCreate($tagNMBHOTITEM, $lParam) Local $iCode = DllStructGetData($tNMBHOTITEM, "Code") Local $hWndFrom = DllStructGetData($tNMBHOTITEM, "hWndFrom") Local $iFlags = DllStructGetData($tNMBHOTITEM, "dwFlags") Local $sText = "" Switch $iCode Case $BCN_HOTITEMCHANGE ; Win XP and Above $sText = "Text=" & _GUICtrlButton_GetText($hWndFrom) If BitAND($iFlags, 0x10) = 0x10 Then _WM_NOTIFY_DebugEvent("$BCN_HOTITEMCHANGE - Entering", $tagNMBHOTITEM, $lParam, "IDFrom", $sText) ElseIf BitAND($iFlags, 0x20) = 0x20 Then _WM_NOTIFY_DebugEvent("$BCN_HOTITEMCHANGE - Leaving", $tagNMBHOTITEM, $lParam, "IDFrom", $sText) EndIf Case $BCN_DROPDOWN _WM_NOTIFY_DebugEvent("$BCN_DROPDOWN", $tagNMBHOTITEM, $lParam, "IDFrom", "") _Popup_Menu($hWndFrom) EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY Func _Popup_Menu($hCtrl) Local $hMenu Local Enum $e_idOpen = 1000, $e_idSave, $e_idInfo $hMenu = _GUICtrlMenu_CreatePopup() _GUICtrlMenu_InsertMenuItem($hMenu, 0, "Open", $e_idOpen) _GUICtrlMenu_InsertMenuItem($hMenu, 1, "Save", $e_idSave) _GUICtrlMenu_InsertMenuItem($hMenu, 3, "", 0) _GUICtrlMenu_InsertMenuItem($hMenu, 3, "Info", $e_idInfo) Switch _GUICtrlMenu_TrackPopupMenu($hMenu, $hCtrl, -1, -1, 1, 1, 2) Case $e_idOpen _MemoWrite("Open - Selected") _GUICtrlButton_SetText($g_hBtn2, "Open") Case $e_idSave _MemoWrite("Save - Selected") _GUICtrlButton_SetText($g_hBtn2, "Save") Case $e_idInfo _MemoWrite("Info - Selected") _GUICtrlButton_SetText($g_hBtn2, "Info") EndSwitch _GUICtrlMenu_DestroyMenu($hMenu) EndFunc ;==>_Popup_Menu ; React on a button click Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg Local $iCode = BitShift($wParam, 16) Local $hCtrl = $lParam Local $sCode, $sText Switch $hCtrl Case $g_hBtn, $g_hBtn2 Switch $iCode Case $BN_CLICKED $sCode = "$BN_CLICKED" Case $BN_PAINT $sCode = "$BN_PAINT" Case $BN_PUSHED $sCode = "$BN_PUSHED" Case $BN_HILITE $sCode = "$BN_HILITE" Case $BN_UNPUSHED $sCode = "$BN_UNPUSHED" Case $BN_UNHILITE $sCode = "$BN_UNHILITE" Case $BN_DISABLE $sCode = "$BN_DISABLE" Case $BN_DBLCLK $sCode = "$BN_DBLCLK" Case $BN_DOUBLECLICKED $sCode = "$BN_DOUBLECLICKED" Case $BN_SETFOCUS $sCode = "$BN_SETFOCUS" Case $BN_KILLFOCUS $sCode = "$BN_KILLFOCUS" EndSwitch $sText = "Text=" & _GUICtrlButton_GetText($hCtrl) _WM_NOTIFY_DebugEvent($sCode, $tagNMHDR, $lParam, "Handle", $sText) Return 0 ; Only workout clicking on the button EndSwitch ; Proceed the default AutoIt3 internal message commands. ; You also can complete let the line out. ; !!! But only 'Return' (without any value) will not proceed ; the default AutoIt3-message in the future !!! Return $GUI_RUNDEFMSG EndFunc ;==>WM_COMMAND ; #FUNCTION# ==================================================================================================================== ; Author.........: UEZ ; =============================================================================================================================== Func _WinAPI_GetDPIForWindow($hWnd) Local $aResult = DllCall('user32.dll', "uint", "GetDpiForWindow", "hwnd", $hWnd) ;requires Win10 v1607+ / no server support If Not IsArray($aResult) Or @error Then Return SetError(1, @extended, 0) If Not $aResult[0] Then Return SetError(2, @extended, 0) Return $aResult[0] EndFunc ;==>_WinAPI_GetDPIForWindow
argumentum Posted 3 hours ago Posted 3 hours ago the right corner should look like the left corner Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting
Solution UEZ Posted 3 hours ago Solution Posted 3 hours ago Try: ... Local $hPath2 = _GDIPlus_PathCreate() _GDIPlus_PathAddArc($hPath2, $iW - 6, 0, 5, 5, 270, 90) _GDIPlus_PathAddLine($hPath2, $iW - 1, 5, $iW - 1, $iH - 6) ; button border fix <<<< need help with curve here _GDIPlus_PathAddArc($hPath2, $iW - 6, $iH - 6, 5, 5, 0, 90) Local $hPen = _GDIPlus_PenCreate(0xFFa0a0a0, 1) Local $hPen2 = _GDIPlus_PenCreate(0xFF9b9b9b, 1) _GDIPlus_GraphicsDrawPath($hBmpCtxt, $hPath, $hPen) _GDIPlus_GraphicsDrawPath($hBmpCtxt, $hPath2, $hPen2) ... WildByDesign 1 Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
ahmet Posted 3 hours ago Posted 3 hours ago Can you draw entire rouned rectangle at once? Func _GDIPlus_PathAddRoundedRect($hPath, $nX, $nY, $nWidth, $nHeight, $nRadius) ;when adding arc $nX and $nY are coordinates of the entire circle, not only the coordinates of the arc segment Local $fP2X=$nX+$nRadius, $fP2y=$nY Local $fP3X=$nX+$nWidth-$nRadius, $fP3Y=$nY Local $fP4X=$nX+$nWidth-2*$nRadius, $fP4Y=$fP2y Local $fP5X=$nX+$nWidth, $fP5Y=$ny+$nRadius Local $fP6X=$fP5X, $fP5Y=$nY+$nHeight-$nRadius Local $fP7X=$fP4X, $fP7Y=$nY+$nHeight-2*$nRadius Local $fP8X=$fP7X+$nRadius, $fP8Y=$nY+$nHeight Local $fP9Y=$fP8Y-2*$nRadius _GDIPlus_PathStartFigure($hPath) _GDIPlus_PathAddArc($hPath,$nX,$nY,2*$nRadius,2*$nRadius,180,90) _GDIPlus_PathAddLine($hPath,$fP2X,$fP2Y,$fP3X,$fP3Y) _GDIPlus_PathAddArc($hPath,$fP4X,$fP4Y,2*$nRadius,2*$nRadius,270,90) _GDIPlus_PathAddLine($hPath,$fP5X,$fP5Y,$fP6X,$fP5Y) _GDIPlus_PathAddArc($hPath,$fP7X,$fP7Y,2*$nRadius,2*$nRadius,0,90) _GDIPlus_PathAddLine($hPath,$fP8X,$fP8Y, $fP2X, $fP8Y) _GDIPlus_PathAddArc($hPath,$nX,$fP9Y,2*$nRadius,2*$nRadius,90,90) _GDIPlus_PathCloseFigure($hPath) EndFunc WildByDesign 1
WildByDesign Posted 2 hours ago Author Posted 2 hours ago 1 hour ago, Polar said: Hi, is the button okay like this? This is very close. Thank you for trying. I appreciate your time. 1 hour ago, UEZ said: Try: This is perfect. Thank you so much. 😎 1 hour ago, ahmet said: Can you draw entire rouned rectangle at once? Doing the whole rectangle would probably make it easier. But unfortunately I don't think that we can do that because the right side of the splitbutton often gets a different background and border color for different states (hover, clicked, etc.). Thank you for sharing that code though, I appreciate it.
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now