2008. július 3., csütörtök

How to implement an OnMouseDown event for the buttons of a TRadioGroup


Problem/Question/Abstract:

I have created a decendant of TRadioGroup called TSuperRadioGroup. With this new control, I have surfaced the onmousedown event. But the event is only triggered when the mouse goes down on the border or caption of the Group, not the Radio Buttons themselves.

Answer:

The solution I use is to register a window procedure for the radiobuttons. You can trap the Windows messages there.

procedure TSuperRadioGroup.RegisterWndProc;
var
  BtnHnd: hWnd;
  ItrBtn: Integer;
begin
  inherited;
  HasWndProc := True;
  BtnHnd := GetWindow(Handle, GW_CHILD);
  ItrBtn := 0;
  while BtnHnd > 0 do
  begin
    if GetWindowLong(BtnHnd, GWL_USERDATA) <> 0 then
      raise Exception.Create('Userdata may not be used');
    ButtonHandle[ItrBtn] := BtnHnd;
    OrigWndProc[ItrBtn] := GetWindowLong(BtnHnd, GWL_WNDPROC);
    SetWindowLong(BtnHnd, GWL_USERDATA, Longint(self));
    SetWindowLong(BtnHnd, GWL_WNDPROC, Longint(@RadioBtnWndProc));
    Inc(ItrBtn);
    BtnHnd := GetWindow(BtnHnd, GW_HWNDNEXT);
  end;
end;

In the RadioBtnWndProc window procedure you can use this code to get at the radiogroup object and the specific button:

Obj := TObject(GetWindowLong(WndHnd, GWL_USERDATA));
if Obj is TSuperRadioGroup then
begin
  RadioGrp := TSuperRadioGroup(Obj);
  for ItrBtn := 0 to RadioGrp.Items.Count - 1 do
  begin
    if WndHnd = RadioGrp.ButtonHandle[ItrBtn] then
    begin
      OrigWndProc := RadioGrp.OrigWndProc[ItrBtn];
      break;
    end;
  end;
end;

If the message is not completely handled, you need to call the original wndproc at the end of your specialized wndproc:

Result := CallWindowProc(Pointer(OrigWndProc), WndHnd, Msg, WParam, LParam);

Nincsenek megjegyzések:

Megjegyzés küldése