Search code examples
inno-setuppascalscript

Custom drawn button in Inno Setup that responds to both mouse and keyboard


I need to create a custom button on Inno Setup page

I need to attach normal events to this new control, such as the mouseover event, keypress event, and also I need to check if this control is the active control on the page or not.

Something like asked here: http://www.delphigroups.info/2/92/498054.html


Solution

  • The actual custom drawn button can handle the mouse clicks. As for the keyboard events and focus, those can he handled by a button that is placed off the form client area.

    Simple example:

    [Code]
    function SetTimer(hWnd: LongWord; nIDEvent, uElapse: LongWord; 
      lpTimerFunc: LongWord): LongWord; external 'SetTimer@user32.dll stdcall';
    
    var
      LastFocusedControl: TWinControl;
      HiddenButton: TButton;
      CustomButton: TBitmapImage;
    
    procedure RedrawCustomButton;
    var
      Canvas: TCanvas;
      Focused: Boolean;
    begin
      Canvas := CustomButton.Bitmap.Canvas;
    
      Focused := (WizardForm.ActiveControl = HiddenButton);
    
      Canvas.Pen.Style := psClear;
      if Focused then Canvas.Brush.Color := clWhite
        else Canvas.Brush.Color := clBtnFace;
      Canvas.Rectangle(1, 1, CustomButton.Bitmap.Width, CustomButton.Bitmap.Height);
    
      Canvas.Pen.Style := psSolid;
      Canvas.Pen.Mode := pmCopy;
      Canvas.Pen.Color := clBlack;
      Canvas.Brush.Style := bsClear;
      Canvas.Rectangle(0, 0, CustomButton.Bitmap.Width, CustomButton.Bitmap.Height);
    end;  
    
    procedure FocusMonitorProc(
      H: LongWord; Msg: LongWord; IdEvent: LongWord; Time: LongWord);
    begin
      if LastFocusedControl <> WizardForm.ActiveControl then
      begin
        if (LastFocusedControl = HiddenButton) or
           (WizardForm.ActiveControl = HiddenButton) then
        begin
          RedrawCustomButton;
        end;
        LastFocusedControl := WizardForm.ActiveControl;
      end;
    end;
    
    procedure ButtonOnClick(Sender: TObject);
    begin
      // When mouse clicked, change focus
      WizardForm.ActiveControl := HiddenButton;
      RedrawCustomButton;
      MsgBox('Button was clicked', mbInformation, MB_OK);
    end;
    
    procedure InitializeWizard();
    var
      Page: TWizardPage;
    begin
      Log('InitializeWizard');
    
      Page := CreateCustomPage(wpWelcome, '', '');
    
      HiddenButton := TNewButton.Create(WizardForm);
      HiddenButton.Parent := Page.Surface;
      HiddenButton.Left := -1000;
      HiddenButton.OnClick := @ButtonOnClick;
    
      CustomButton := TBitmapImage.Create(WizardForm);
      CustomButton.Parent := Page.Surface;
      CustomButton.Top := 0;
      CustomButton.Left := 0;
      CustomButton.Width := ScaleX(128);
      CustomButton.Height := ScaleX(32);
      CustomButton.Bitmap.Width := CustomButton.Width;
      CustomButton.Bitmap.Height := CustomButton.Height;
      CustomButton.OnClick := @ButtonOnClick;
      RedrawCustomButton;
    
      // Set up 50ms timer to monitor the focus
      SetTimer(0, 0, 50, CreateCallback(@FocusMonitorProc));
    end;
    

    For focus monitoring the code uses the technique described in my answer to your previous question Detect when button/control is focused in Inno Setup.

    When focused:
    enter image description here

    When not focused: