diff --git a/lcl/controls.pp b/lcl/controls.pp index 7c2d4ac197..994c48c9db 100644 --- a/lcl/controls.pp +++ b/lcl/controls.pp @@ -2377,8 +2377,10 @@ begin AWinControl := FindOwnerControl(Handle); if AWinControl <> nil then begin - with TLMessage(Message) do - Result := AWinControl.Perform(Msg + CN_BASE, WParam, LParam); + { do not use Perform, use WndProc so we can save the Result } + Inc(TLMessage(Message).Msg, CN_BASE); + AWinControl.WndProc(TLMessage(Message)); + Dec(TLMessage(Message).Msg, CN_BASE); Result := true; end; end; diff --git a/lcl/interfaces/win32/win32callback.inc b/lcl/interfaces/win32/win32callback.inc index e6b5c82e21..080ca8c371 100644 --- a/lcl/interfaces/win32/win32callback.inc +++ b/lcl/interfaces/win32/win32callback.inc @@ -290,7 +290,7 @@ Var end; end; - procedure SendPaintMessage; + procedure SendPaintMessage(ControlDC: HDC); var DC: HDC; DoubleBufferBitmapOld: HBITMAP; @@ -331,7 +331,7 @@ Var // WM_ERASEBKGND and WM_CTLCOLORSTATIC for native controls // sent by default paint handler if WindowInfo^.isTabPage or (needParentPaint - and (not isNativeControl or (WParam <> 0))) then + and (not isNativeControl or (ControlDC <> 0))) then begin ParentPaintWindow := Window; lNotebookFound := false; @@ -350,7 +350,7 @@ Var PushEraseBkgndCommand(ecDiscard); // check if double buffering is requested - useDoubleBuffer := (WParam = 0) and (lWinControl.DoubleBuffered + useDoubleBuffer := (ControlDC = 0) and (lWinControl.DoubleBuffered or TWin32WidgetSet(WidgetSet).ThemesActive); {$ifdef MSG_DEBUG} if useDoubleBuffer and (DoubleBufferDC <> 0) then @@ -386,7 +386,7 @@ Var WinProcess := false; try - if WParam = 0 then + if ControlDC = 0 then begin // ignore first erase background on themed control, paint will do everything if TWin32WidgetSet(WidgetSet).ThemesActive then @@ -428,7 +428,7 @@ Var Windows.DeleteObject(PaintRegion); end; end else begin - DC := WParam; + DC := ControlDC; PaintRegion := 0; end; if ParentPaintWindow <> 0 then @@ -463,7 +463,7 @@ Var Windows.SendMessage(ParentPaintWindow, WM_PAINT, PaintMsg.DC, 0); Windows.RestoreDC(PaintMsg.DC, DCIndex); end; - if (WParam = 0) or not needParentPaint then + if (ControlDC = 0) or not needParentPaint then begin DCIndex := Windows.SaveDC(PaintMsg.DC); MoveWindowOrgEx(PaintMsg.DC, ORect.Left, ORect.Top); @@ -478,7 +478,7 @@ Var end; if useDoubleBuffer then Windows.BitBlt(DC, 0, 0, WindowWidth, WindowHeight, DoubleBufferDC, 0, 0, SRCCOPY); - if WParam = 0 then + if ControlDC = 0 then Windows.EndPaint(Window, @PS); finally if useDoubleBuffer then @@ -500,6 +500,14 @@ Var end; end; + procedure SendParentPaintMessage(Window, Parent: HWND; ControlDC: HDC); + begin + GetWin32ControlPos(Window, Parent, P.X, P.Y); + MoveWindowOrgEx(ControlDC, -P.X, -P.Y); + SendPaintMessage(ControlDC); + MoveWindowOrgEx(ControlDC, P.X, P.Y); + end; + procedure CheckListBoxLButtonDown; var I: Integer; @@ -1182,13 +1190,11 @@ begin case Msg of WM_CTLCOLORSTATIC, WM_CTLCOLORBTN: begin - if GetNeedParentPaint(ChildWindowInfo, ChildWinControl) then + if GetNeedParentPaint(ChildWindowInfo, ChildWinControl) + and not ChildWindowInfo^.ThemedCustomDraw then begin // need to draw transparently, draw background - GetWin32ControlPos(LParam, Window, P.X, P.Y); - MoveWindowOrgEx(WParam, -P.X, -P.Y); - SendPaintMessage; - MoveWindowOrgEx(WParam, P.X, P.Y); + SendParentPaintMessage(LParam, Window, WParam); LMessage.Result := GetStockObject(HOLLOW_BRUSH); SetBkMode(WParam, TRANSPARENT); WinProcess := false; @@ -1360,7 +1366,7 @@ begin LMessage.LParam := LParam; end; end else begin - SendPaintMessage; + SendPaintMessage(WParam); LMessage.Result := 1; end; WinProcess := false; @@ -1696,7 +1702,28 @@ begin NM_CUSTOMDRAW: begin if WindowInfo^.WinControl is TCustomListView - then HandleListViewCustomDraw(TCustomListViewAccess(WindowInfo^.WinControl)); + then HandleListViewCustomDraw(TCustomListViewAccess(WindowInfo^.WinControl)) + else if GetNeedParentPaint(WindowInfo, lWinControl) + and WindowInfo^.ThemedCustomDraw then + begin + case PNMCustomDraw(LParam)^.dwDrawStage of + CDDS_PREPAINT: + begin + Result := CDRF_NOTIFYITEMDRAW; + WinProcess := false; + end; + CDDS_ITEMPREPAINT: + begin + case PNMCustomDraw(LParam)^.dwItemSpec of + TBCD_TICS, TBCD_CHANNEL: + SendParentPaintMessage(Window, Windows.GetParent(Window), + PNMCustomDraw(LParam)^.hDC); + end; + Result := CDRF_DODEFAULT; + WinProcess := false; + end; + end; + end; end; end; end; @@ -1704,7 +1731,7 @@ begin end; WM_PAINT: Begin - SendPaintMessage; + SendPaintMessage(WParam); // SendPaintMessage sets winprocess to false End; WM_PASTE: diff --git a/lcl/interfaces/win32/win32proc.pp b/lcl/interfaces/win32/win32proc.pp index cce40abda5..5e1ba31637 100644 --- a/lcl/interfaces/win32/win32proc.pp +++ b/lcl/interfaces/win32/win32proc.pp @@ -51,6 +51,7 @@ Type isComboEdit: boolean; // is buddy of combobox, the edit control isChildEdit: boolean; // is buddy edit of a control isGroupBox: boolean; // is groupbox, and does not have themed tabpage as parent + ThemedCustomDraw: boolean;// controls needs themed drawing in wm_notify/nm_customdraw MaxLength: integer; DrawItemIndex: integer; // in case of listbox, when handling WM_DRAWITEM DrawItemSelected: boolean;// whether this item is selected LB_GETSEL not uptodate yet diff --git a/lcl/interfaces/win32/win32wscomctrls.pp b/lcl/interfaces/win32/win32wscomctrls.pp index 9d5b3a9bb7..475abda832 100644 --- a/lcl/interfaces/win32/win32wscomctrls.pp +++ b/lcl/interfaces/win32/win32wscomctrls.pp @@ -524,6 +524,7 @@ begin end; // create window FinishCreateWindow(AWinControl, Params, false); + Params.WindowInfo^.ThemedCustomDraw := true; Result := Params.Window; end; diff --git a/lcl/interfaces/win32/winext.pas b/lcl/interfaces/win32/winext.pas index dca696c205..247b707827 100644 --- a/lcl/interfaces/win32/winext.pas +++ b/lcl/interfaces/win32/winext.pas @@ -42,6 +42,17 @@ Type { Pointer to @link(COMBOBOXINFO) } PComboBoxInfo = ^COMBOBOXINFO; + TNMCustomDraw = record + hdr : NMHDR; + dwDrawStage: DWORD; + hdc : HDC; + rc : TRECT; + dwItemSpec : DWORD; + uItemState : UINT; + lItemlParam: LPARAM; + end; + PNMCustomDraw=^TNMCustomDraw; + TNMLVCustomDraw = Record hdr : NMHDR; dwDrawStage : DWORD; @@ -192,6 +203,11 @@ Const CDRF_NOTIFYSUBITEMDRAW = $20; // flags are the same, we can distinguish by context CDRF_NOTIFYPOSTERASE = $40; CDRF_NOTIFYITEMERASE = $80; + + // trackbar customdraw + TBCD_TICS = $01; + TBCD_THUMB = $02; + TBCD_CHANNEL = $03; // progressbar PBM_SETRANGE32 = 1030;