davornik 4 Posted May 17 Is it possible to detect OnMouseDown and on MouseUp events on the TButtonedEdit RightButton (TEditButton)? I am trying to set it to Show/Hide password when I press/unpress the right button, but there is only an OnClick event for the right button. Tried also subclassing, but there is no handle for the right button in TButtonedEdit? procedure TForm1.FormCreate(Sender: TObject); begin //SetWindowSubclass(ButtonedEdit1.RightButton.Handle, @ButtonedEditSubclassProc, 1, DWORD_PTR(ButtonedEdit1.RightButton)); <- no Handle for RightButton SetWindowSubclass(ButtonedEdit1.Handle, @ButtonedEditSubclassProc, 1, DWORD_PTR(ButtonedEdit1)); end; function ButtonedEditSubclassProc(hWnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM; uIdSubclass: UINT_PTR; dwRefData: DWORD_PTR): LRESULT; stdcall; begin case uMsg of WM_LBUTTONDOWN: Form1.ButtonedEdit1.PasswordChar:=#0; WM_LBUTTONUP: Form1.ButtonedEdit1.PasswordChar:='*'; WM_NCDESTROY: RemoveWindowSubclass(hWnd, @ButtonedEditSubclassProc, uIdSubclass); end; Result := DefSubclassProc(hWnd, uMsg, wParam, lParam); end; Password is hidden When I press right button is it possible for password to be shown and on unpress to be hidden again? Share this post Link to post
Uwe Raabe 2156 Posted May 18 (edited) The buttons of a TButtonedEdit are no controls, so there simply is no handle. Instead they provide an instance FGlyph of a private type TGlyph derived from TCustomControl, which handles the mouse events. This control has the edit control as parent. Perhaps you can achieve your goal by deriving from TButtonControl and override GetEditButtonClass. This gives you access to the protected FGlyph and allows to replace it with a derived class implementing the requested behavior. Edited May 18 by Uwe Raabe Share this post Link to post
davornik 4 Posted May 18 1 hour ago, Uwe Raabe said: The buttons of a TButtonedEdit are no controls, so there simply is no handle. Instead they provide an instance FGlyph of a private type TGlyph derived from TCustomControl, which handles the mouse events. This control has the edit control as parent. Perhaps you can achieve your goal by deriving from TButtonControl and override GetEditButtonClass. This gives you access to the protected FGlyph and allows to replace it with a derived class implementing the requested behavior. If I correctly understood goal is to then find private TGlyph class name and then its handle? TGlyph is private inside the Vcl.ButtonedEdit unit. I can search for Glyph handle, and do GetWindowLongPtr/SetWindowLongPtr to detect WM_LBUTTONDOWN and WM_LBUTTONUP messages. var OldGlyphWndProc: Pointer = nil; function CustomGlyphWndProc(hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; begin if Msg = WM_LBUTTONUP then Form1.ButtonedEdit1.PasswordChar:='*' // <- this does not fire else if Msg = WM_LBUTTONDOWN then Form1.ButtonedEdit1.PasswordChar:=#0; // <- this now fires Result := CallWindowProc(OldGlyphWndProc, hWnd, Msg, wParam, lParam); end; procedure SubclassRightButtonGlyph(Edit: TButtonedEdit); var GlyphHandle: HWND; ClassName: array[0..255] of Char; begin GlyphHandle := GetWindow(Edit.Handle, GW_CHILD); while GlyphHandle <> 0 do begin if GetClassName(GlyphHandle, ClassName, Length(ClassName)) > 0 then if ClassName = 'TEditButton.TGlyph' then begin OldGlyphWndProc := Pointer(GetWindowLongPtr(GlyphHandle, GWL_WNDPROC)); SetWindowLongPtr(GlyphHandle, GWL_WNDPROC, LONG_PTR(@CustomGlyphWndProc)); Break; end; GlyphHandle := GetWindow(Edit.Handle, GW_HWNDNEXT); end; end; procedure TForm1.FormCreate(Sender: TObject); begin SubclassRightButtonGlyph(ButtonedEdit1); end; How I can see password OnMouseDown, but it does not goes to hidden OnMouseUp? Share this post Link to post
Uwe Raabe 2156 Posted May 18 The TGlyph type being private and Glyph property being protected makes everything a bit cumbersome. Fortunately there is a trick to inject a message handler without subclassing. type TEditButtonHelper = class helper for TEditButton public procedure LinkMessageHandler; end; TGlyphMessageHandler = class(TWinControlMessageHandler) protected function HandleMessage(var Message: TMessage): Boolean; override; end; function TGlyphMessageHandler.HandleMessage(var Message: TMessage): Boolean; begin var edt := TButtonedEdit(Control.Parent); case Message.Msg of WM_LBUTTONDOWN: edt.PasswordChar := #0; WM_LBUTTONUP: edt.PasswordChar := '*'; end; Result := inherited; end; procedure TEditButtonHelper.LinkMessageHandler; begin Glyph.InitMessageHandler(TGlyphMessageHandler); end; procedure TForm1.FormCreate(Sender: TObject); begin ButtonedEdit1.RightButton.LinkMessageHandler; end; 1 Share this post Link to post