WildByDesign Posted 54 minutes ago Posted 54 minutes ago I have had some success recently while working on the Rebar control subclass that will eventually be added to GUIDarkTheme UDF. The dark mode colors used for the background and text are working well now. Goal: Draw dotted lines over existing white (0xf0f0f0) gripper edge on bands I've seen C++ projects use Polyline WinAPI used for this Although other dotted line methods could be used Draw chevrons when needed I don't even know how to make chevrons appear in Rebar (not familiar with Rebar) I've seen C++ projects use DrawText to draw chevron shape/glyph from text I have tried a bunch of things to draw dotted lines over the existing white gripper. The only success that I ever had was only drawing on the first band. So I think that my mistake was drawing on the Rect from the whole Rebar instead of the Rect of individual bands. I don't know how to do that or how to get DC for individual bands. If anybody can help with the dotted lines for gripper edges and chevrons, I would really appreciate it. If that works out successfully, then I can add the checking of style parts after to ensure that we only draw those on bands that are using them at the time of drawing. Some relevant C++ code from win32-darkmodelib project: expandcollapse popup/** * @brief Applies custom drawing to a rebar control during `CDDS_PREPAINT`. * * Paints chevrons and 'gripper' edges for all bands if applicable. * * @param[in] lpnmcd Reference to `LPNMCUSTOMDRAW`. * @return `CDRF_SKIPDEFAULT` if drawing was applied. * * @see darkRebarNotifyCustomDraw() */ [[nodiscard]] static LRESULT prepaintRebar(const LPNMCUSTOMDRAW& lpnmcd) noexcept { ::FillRect(lpnmcd->hdc, &lpnmcd->rc, dmlib::getDlgBackgroundBrush()); REBARBANDINFO rbBand{}; rbBand.cbSize = sizeof(REBARBANDINFO); rbBand.fMask = RBBIM_STYLE | RBBIM_CHEVRONLOCATION | RBBIM_CHEVRONSTATE; const auto nBands = static_cast<UINT>(::SendMessage(lpnmcd->hdr.hwndFrom, RB_GETBANDCOUNT, 0, 0)); for (UINT i = 0; i < nBands; ++i) { ::SendMessage(lpnmcd->hdr.hwndFrom, RB_GETBANDINFO, static_cast<WPARAM>(i), reinterpret_cast<LPARAM>(&rbBand)); // paints chevron if ((rbBand.fStyle & RBBS_USECHEVRON) == RBBS_USECHEVRON && (rbBand.rcChevronLocation.right - rbBand.rcChevronLocation.left) > 0) { static const int roundness = dmlib::isAtLeastWindows11() ? dmlib_paint::kWin11CornerRoundness + 1 : 0; const bool isHot = (rbBand.uChevronState & STATE_SYSTEM_HOTTRACKED) == STATE_SYSTEM_HOTTRACKED; const bool isPressed = (rbBand.uChevronState & STATE_SYSTEM_PRESSED) == STATE_SYSTEM_PRESSED; if (isHot) { dmlib_paint::paintRoundRect(lpnmcd->hdc, rbBand.rcChevronLocation, dmlib::getHotEdgePen(), dmlib::getHotBackgroundBrush(), roundness, roundness); } else if (isPressed) { dmlib_paint::paintRoundRect(lpnmcd->hdc, rbBand.rcChevronLocation, dmlib::getEdgePen(), dmlib::getCtrlBackgroundBrush(), roundness, roundness); } ::SetTextColor(lpnmcd->hdc, isHot ? dmlib::getTextColor() : dmlib::getDarkerTextColor()); ::SetBkMode(lpnmcd->hdc, TRANSPARENT); const auto hFont = dmlib_paint::GdiObject{ lpnmcd->hdc, lpnmcd->hdr.hwndFrom }; static constexpr UINT dtFlags = DT_CENTER | DT_TOP | DT_SINGLELINE | DT_NOCLIP | DT_NOPREFIX; ::DrawText(lpnmcd->hdc, dmlib_glyph::kChevron, -1, &rbBand.rcChevronLocation, dtFlags); } // paints gripper edge if ((rbBand.fStyle & RBBS_GRIPPERALWAYS) == RBBS_GRIPPERALWAYS && ((rbBand.fStyle & RBBS_FIXEDSIZE) != RBBS_FIXEDSIZE || (rbBand.fStyle & RBBS_NOGRIPPER) != RBBS_NOGRIPPER)) { auto holdPen = static_cast<HPEN>(::SelectObject(lpnmcd->hdc, dmlib::getDarkerTextPen())); RECT rcBand{}; ::SendMessage(lpnmcd->hdr.hwndFrom, RB_GETRECT, static_cast<WPARAM>(i), reinterpret_cast<LPARAM>(&rcBand)); static constexpr LONG offset = 5; const std::array<POINT, 2> edges{ { { rcBand.left, rcBand.top + offset}, { rcBand.left, rcBand.bottom - offset} } }; ::Polyline(lpnmcd->hdc, edges.data(), static_cast<int>(edges.size())); ::SelectObject(lpnmcd->hdc, holdPen); } } return CDRF_SKIPDEFAULT; } Here is my current Rebar subclass testing code: expandcollapse popup#include <WinAPIGdi.au3> #include <WinAPITheme.au3> #include <WindowsNotifsConstants.au3> #include <ToolbarConstants.au3> #include <RebarConstants.au3> #include <AutoItConstants.au3> #include <GuiComboBox.au3> #include <GUIConstantsEx.au3> #include <GuiDateTimePicker.au3> #include <GuiEdit.au3> #include <GuiReBar.au3> #include <GuiToolbar.au3> #include <StructureConstants.au3> #include <WinAPIConstants.au3> #include <WindowsStylesConstants.au3> #include <APIGdiConstants.au3> ; Initialize System DPI awareness DllCall("user32.dll", "bool", "SetProcessDpiAwarenessContext", @AutoItX64 ? "int64" : "int", -2) Global Const $TBCDRF_USECDCOLORS = 0x800000 Global Const $tagNMTBCUSTOMDRAW = $tagNMHDR & ";dword dwDrawStage;handle hdc;" & $tagRECT & ";dword_ptr dwItemSpec;uint uItemState;lparam lItemlParam;" & _ "ptr hbrMonoDither;ptr hbrLines;ptr hpenLines;dword clrText;dword clrMark;dword clrTextHighlight;dword clrBtnFace;dword clrBtnHighlight;dword clrHighlightHotTrack;" & _ "long TextLeft;long TextTop;long TextRight;long TextBottom;int nStringBkMode;int nHLStringBkMode;int iListGap;" Global $g_hReBar, $hGui Example() Func Example() $hGui = GUICreate("Rebar Create (v" & @AutoItVersion & ")", 400, 396, -1, -1, $WS_OVERLAPPEDWINDOW) GUISetBkColor(0x202020) ; create the rebar control $g_hReBar = _GUICtrlRebar_Create($hGui, BitOR($CCS_TOP, $WS_BORDER, $RBS_VARHEIGHT, $RBS_AUTOSIZE, $RBS_BANDBORDERS)) _GUICtrlRebar_SetColorScheme($g_hReBar, 0x383838, 0x383838) ; create a toolbar to put in the rebar Local $hToolbar = _GUICtrlToolbar_Create($hGui, BitOR($TBSTYLE_FLAT, $CCS_NORESIZE, $CCS_NOPARENTALIGN)) _GUICtrlToolbar_SetColorScheme($hToolbar, 0x383838, 0x383838) _GUICtrlToolbar_SetStyleTransparent($hToolbar, False) ; Add standard system bitmaps _GUICtrlToolbar_AddBitmap($hToolbar, 1, -1, $IDB_STD_LARGE_COLOR) ; Add strings Local $aStrings[4] $aStrings[0] = _GUICtrlToolbar_AddString($hToolbar, "&New") $aStrings[1] = _GUICtrlToolbar_AddString($hToolbar, "&Open") $aStrings[2] = _GUICtrlToolbar_AddString($hToolbar, "&Save") $aStrings[3] = _GUICtrlToolbar_AddString($hToolbar, "&Help") ; Add buttons Local Enum $e_idNew = 1000, $e_idOpen, $e_idSave, $e_idHelp _GUICtrlToolbar_AddButton($hToolbar, $e_idNew, $STD_FILENEW, $aStrings[0]) _GUICtrlToolbar_AddButton($hToolbar, $e_idOpen, $STD_FILEOPEN, $aStrings[1]) _GUICtrlToolbar_AddButton($hToolbar, $e_idSave, $STD_FILESAVE, $aStrings[2], $BTNS_CHECK) _GUICtrlToolbar_AddButtonSep($hToolbar) _GUICtrlToolbar_AddButton($hToolbar, $e_idHelp, $STD_HELP, $aStrings[3]) ; create a combobox to put in the rebar Local $hCombo = _GUICtrlComboBox_Create($hGui, "", 0, 0, 120) _GUICtrlComboBox_BeginUpdate($hCombo) _GUICtrlComboBox_AddDir($hCombo, @WindowsDir & "\*.exe") _GUICtrlComboBox_EndUpdate($hCombo) ; create a date time picker to put in the rebar Local $hDTP = _GUICtrlDTP_Create($hGui, 0, 0, 190) ; create a input box to put in the rebar Local $hInput = _GUICtrlEdit_Create($hGui, "Input control", 0, 0, 120, 20, 0) ; add band with control _GUICtrlRebar_AddBand($g_hReBar, $hCombo, 120, 200, "Dir *.exe") ; add band with date time picker _GUICtrlRebar_AddBand($g_hReBar, $hDTP, 120) ; add band with toolbar to beginning of rebar _GUICtrlRebar_AddToolBarBand($g_hReBar, $hToolbar, "", 0) ;add another control _GUICtrlRebar_AddBand($g_hReBar, $hInput, 120, 200, "Name:") _WinAPI_SetWindowTheme($g_hReBar, "", "") GUIRegisterMsg($WM_NOTIFY, WM_NOTIFY) GUISetState(@SW_SHOW) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd EndFunc ;==>Example Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam) Local $tTool = DllStructCreate($tagNMTBCUSTOMDRAW, $lParam) If $tTool.Code <> $NM_CUSTOMDRAW Then Return $GUI_RUNDEFMSG Local $dwDrawStage = $tTool.dwDrawStage Local $sClass = _WinAPI_GetClassName($tTool.hWndFrom) Switch $sClass Case "ReBarWindow32" Switch $dwDrawStage Case $CDDS_PREPAINT Local $hBrush = _WinAPI_CreateSolidBrush(0x383838) Local $tRect = DllStructCreate($tagRECT, DllStructGetPtr($tTool, "left")) _WinAPI_FillRect($tTool.hdc, $tRect, $hBrush) _WinAPI_DeleteObject($hBrush) Return $CDRF_NOTIFYITEMDRAW Case $CDDS_ITEMPREPAINT _WinAPI_SetTextColor($tTool.hdc, 0xFFFFFF) _WinAPI_SetBkMode($tTool.hdc, $TRANSPARENT) Return $CDRF_NEWFONT EndSwitch Case "ToolbarWindow32" Switch $dwDrawStage Case $CDDS_PREPAINT Local $hBrush = _WinAPI_CreateSolidBrush(0x383838) Local $tRect = DllStructCreate($tagRECT, DllStructGetPtr($tTool, "left")) _WinAPI_FillRect($tTool.hdc, $tRect, $hBrush) _WinAPI_DeleteObject($hBrush) Return $CDRF_NOTIFYITEMDRAW Case $CDDS_ITEMPREPAINT Local $iState = $tTool.uItemState If BitAND($iState, $CDIS_HOT) Then $tTool.clrText = 0xFFFFFF $tTool.clrTextHighlight = 0xFFFFFF Local $tRect = DllStructCreate($tagRECT, DllStructGetPtr($tTool, "left")) Local $hPen = _WinAPI_CreatePen($PS_SOLID, 1, 0x121212) Local $hOldPen = _WinAPI_SelectObject($tTool.hdc, $hPen) Local $hBrush = _WinAPI_CreateSolidBrush(BitAND($iState, $CDIS_SELECTED) ? 0x484848 : 0x606060) Local $hObj = _WinAPI_SelectObject($tTool.hdc, $hBrush) _WinAPI_InflateRect($tRect, 0, -2) _WinAPI_RoundRect($tTool.hdc, $tRect, 8, 8) _WinAPI_SelectObject($tTool.hdc, $hObj) _WinAPI_SelectObject($tTool.hdc, $hOldPen) _WinAPI_DeleteObject($hBrush) _WinAPI_DeleteObject($hPen) ; clear item state or else this will not work $tTool.uItemState = Null Return $TBCDRF_USECDCOLORS EndIf If BitAND($iState, $CDIS_CHECKED) Then $tTool.clrText = 0xFFFFFF $tTool.clrTextHighlight = 0xFFFFFF Local $tRect = DllStructCreate($tagRECT, DllStructGetPtr($tTool, "left")) Local $hPen = _WinAPI_CreatePen($PS_SOLID, 1, 0x121212) Local $hOldPen = _WinAPI_SelectObject($tTool.hdc, $hPen) Local $hBrush = _WinAPI_CreateSolidBrush(BitAND($iState, $CDIS_SELECTED) ? 0x484848 : 0x606060) Local $hObj = _WinAPI_SelectObject($tTool.hdc, $hBrush) _WinAPI_InflateRect($tRect, 0, -2) _WinAPI_RoundRect($tTool.hdc, $tRect, 8, 8) _WinAPI_SelectObject($tTool.hdc, $hObj) _WinAPI_SelectObject($tTool.hdc, $hOldPen) _WinAPI_DeleteObject($hBrush) _WinAPI_DeleteObject($hPen) ; clear item state or else this will not work $tTool.uItemState = Null Return $TBCDRF_USECDCOLORS EndIf If Not BitAND($iState, $CDIS_DISABLED) Then $tTool.clrText = 0xFFFFFF $tTool.clrTextHighlight = 0xFFFFFF Return $TBCDRF_USECDCOLORS EndIf EndSwitch Case Else Return $GUI_RUNDEFMSG EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY
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