Autor Beitrag
Burgpflanze
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 67

Windows2000 Prof. SP4
Delphi7 Enterprise
BeitragVerfasst: So 25.08.02 10:50 
Wer unter WindowsXP programmiert und sein Programm so anlegt, das es die Visuellen Styles von XP benutzt, wird festgestellt haben, das der Gedrückt-Status eines TToolButtons nicht gezeichnet wird, wenn er den Style "tbsDropDown" hat (dies betrifft nicht den Teil des Buttons, der das dazugehörige DropDownMenu öffnet).

Da der ThemeManager von Mike Lischke leider hier keine Abhilfe schafft, habe ich in der Unit "ComCtrls.pas" einige kleine Änderungen eingefügt, welche dafür sorgen, das auch dann der Button korrekt dargestellt wird.

Damit keine Mißverständnisse auftreten, poste ich hier die komplette Procedure "TToolbar.WndProc". Die von mir gemachten Änderungen sind gekennzeichnet.
( Änderungen stehen zwischen { <<< ANFANG >>> } und { <<< ENDE >>> } )

ausblenden volle Höhe Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
procedure TToolBar.WndProc(var Message: TMessage);
var
  Control: TControl;
  CapControl: TControl;
  Msg: TMsg;

{ <<< ANFANG >>> }
  State: Integer;
  MousePos: TPoint;

  function IsWinXP: Boolean;
  var
    osVersionInfo: TOSVersionInfo;
  begin
    osVersionInfo.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);
    if GetVersionEx(osVersionInfo) then Result := ((osVersionInfo.dwMajorVersion = 5) and
      (osVersionInfo.dwMinorVersion > 0)) or (osVersionInfo.dwMajorVersion > 5)
    else
      Result := False;
  end;
{ <<< ENDE >>> }

  function IsToolButtonMouseMsg(var Message: TWMMouse): Boolean;
  begin
    if GetCapture = Handle then
    begin
      CapControl := GetCaptureControl;
      if (CapControl <> nil) and (CapControl.Parent <> Self) then
        CapControl := nil;
    end
    else
      CapControl := nil;
    Control := ControlAtPos(SmallPointToPoint(Message.Pos), False);
    Result := (Control <> nil) and (Control is TToolButton) and
      not Control.Dragging;
  end;

  procedure SendDropdownMsg(Button: TToolButton);
  var
    Msg: TNMToolBar;
  begin
    FillChar(Msg, SizeOf(Msg), 0);
    with Msg, hdr do
    begin
      hwndFrom := Handle;
      idFrom := Handle;
      code := TBN_DROPDOWN;
      iItem := Button.Index;
    end;
    SendMessage(Handle, WM_NOTIFY, Handle, Longint(@Msg));
  end;

begin
  if not (csDesigning in ComponentState) then
  begin
    case Message.Msg of
      WM_MOUSEMOVE:
        begin
          if IsToolButtonMouseMsg(TWMMouse(Message)) then
          begin
            if TControlAccess(Control).DragMode <> dmAutomatic then DefaultHandler(Message);

{ <<< ANFANG >>> }
            if IsWinXP and (TToolButton(Control).Style = tbsDropDown) then
            begin
              GetCursorPos(MousePos);
              MousePos := ScreenToClient(MousePos);
              with TToolButton(Control) do
              begin
                if (MousePos.X < Left) or (MousePos.X > Left + Width) or
                  (MousePos.Y < Top) or (MousePos.Y > Top + Height) then
                begin
                  State := SendMessage(Handle, TB_GETSTATE, Index, 0);
                  State := State and not TB_PRESSBUTTON;
                  SendMessage(Handle, TB_SETSTATE, Index, MakeLong(State, 0));
                end;
              end;
            end;
{ <<< ENDE >>> }

          end
          else
            DefaultHandler(Message);
        end;
      WM_LBUTTONUP:
        if IsToolButtonMouseMsg(TWMMouse(Message)) then
        begin
          State := SendMessage(Handle, TB_GETSTATE, TToolButton(Control).Index, 0);

{ <<< ANFANG >>> }
          if State and TB_PRESSBUTTON <> 0 then DefaultHandler(Message);
{ <<< ENDE >>> }

          if (CapControl = Control) { <<< ANFANG >>> } or
            (IsWinXP and (TToolButton(Control).Style = tbsDropDown)) { <<< ENDE >>> } then
          begin
            with TToolButton(Control) do
            begin
              if Down and Grouped and AllowAllUp and (Style = tbsCheck) then Down := False;
              UpdateButtonStates;
              
{ <<< ANFANG >>> }
              if IsWinXP and (Style = tbsDropDown) and (State and TB_PRESSBUTTON <> 0) then
                  Click;
{ <<< ENDE >>> }

            end;
          end
          else if (CapControl is TToolButton) or
            (TToolButton(Control).Style = tbsDropDown) then Exit;
        end;
      WM_LBUTTONDOWN, WM_LBUTTONDBLCLK:
        if IsToolButtonMouseMsg(TWMMouse(Message)) then
        begin
          with TToolButton(Control) do
          begin
            if FInMenuLoop and Self.MouseCapture then MouseCapture := True;
            if (Style <> tbsDropDown) or
              (GetComCtlVersion >= ComCtlVersionIE4) and
              (TWMMouse(Message).XPos < Left + ButtonWidth) then
            begin

{ <<< ANFANG >>> }
              if IsWinXP and (Style = tbsDropDown) then
              begin
                State := SendMessage(Handle, TB_GETSTATE, Index, 0);
                State := State or TB_PRESSBUTTON and not TB_INDETERMINATE;
                SendMessage(Handle, TB_SETSTATE, Index, MakeLong(State, 0));
              end
              else
{ <<< ENDE >>> }

                inherited WndProc(Message);
            end;
          end;
          if not Control.Dragging then DefaultHandler(Message);
          if (TToolButton(Control).Style <> tbsDropDown) and
            ((TToolButton(Control).DropdownMenu <> nil) or
            (TToolButton(Control).MenuItem <> nil)) then
          begin
            try
              SendDropDownMsg(TToolButton(Control));
            finally
              Msg.Message := 0;
              if PeekMessage(Msg, Handle, WM_LBUTTONDOWN, WM_LBUTTONDOWN,
                PM_REMOVE) and (Msg.Message = WM_QUIT) then PostQuitMessage(Msg.WParam)
              else
              begin
                Message.Msg := WM_LBUTTONUP;
                Dispatch(Message);
              end;
            end;
          end;
          Exit;
        end;
    end
  end;
  inherited WndProc(Message);
end;


Damit die Änderungen aktiv werden können, muss anschliessend das VCL-Verzeichnis noch zum Library-Pfad hinzugefügt werden, am Besten an erster Stelle stehend.


Gruss, Burgpflanze

>>>>> Jetzt wird das Click-Ereignis ausgelöst.
>>>>> Button wird jetzt korrekt gezeichnet, wenn man mit gedrückter Maustaste einen Button verläßt.
>>>>> Jetzt wird auch kein falsches Click-Ereignis mehr ausgelöst.

_________________
Gruss, Burgpflanze


Zuletzt bearbeitet von Burgpflanze am So 25.08.02 19:28, insgesamt 3-mal bearbeitet
toms
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1099
Erhaltene Danke: 2



BeitragVerfasst: So 25.08.02 15:35 
Hi,

Zuerst mal danke für den Code.
Habe die Änderungen mal soweit vorgenommen. (D6)
Der "Gedrückt-Status" eines TToolButtons wird nun tatsächlich
angezeigt, jedoch wird das OnClick-Ereignis nicht ausgelöst,
wenn ich die Maus wieder loslasse.
toms
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1099
Erhaltene Danke: 2



BeitragVerfasst: So 25.08.02 16:00 
Thx, das OnClick funktioniert nun.

Jetzt habe ich aber noch ein weiteres Problem entdeckt.
Wenn man auf einen TToolButton klickt (Mouse Button down)
und die Maus ausserhalb des TToolButtons bewegt und dann
loslässt, dann bleibt der "Gedrückt-Status".
toms
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1099
Erhaltene Danke: 2



BeitragVerfasst: So 25.08.02 18:42 
Es klappt nun mit dem "Gedrückt-Status".
Weiss zwar nicht, warum du überall die Beschränkung

... and (Style = tbsDropDown) ..

hinzugefügt hast.
Somit wird bei TToolButtons mit Style tbsButton wieder kein
OnClick Ereignis ausgelöst.

Hab jedoch für mich diese "Beschränkung" aufgehoben.
toms
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1099
Erhaltene Danke: 2



BeitragVerfasst: So 25.08.02 18:49 
Und dann gibt's noch eine weitere Unschönheit:

Wenn man auf einen TToolButton1 klickt (Mouse Button down)
und die Maus über einen anderen TToolButton2 bewegt und dann
die Maus-Taste loslässt, wird das OnClick Ereignis von TToolButton1 ausgelöst, obwohl es eigentlich gar nicht dürfte.