Skip to content
⌘ NSIS Forum Archive

stop 'back' message in plugin

6 posts

sfx09#

stop 'back' message in plugin

Hello!

I'm doing a plugin for NSIS with a several forms (!), which are changing by clicking on 'Next' or 'Back' buttons.
My plugin work via Page Custom at this steps-condition:

!insertmacro MUI_PAGE_WELCOME
Page Custom MyPlugShow
!insertmacro MULTIUSER_PAGE_INSTALLMODE

Also, I try to change 'Cancel' button to Skip-functionality. So, if I try to click on 'Skip' ('Cancel') button, after click on the 'Next' button - all work fine - plugin go to MULTIUSER_PAGE_INSTALLMODE. But, if I try to click on 'Skip', after click on the 'Back' button - plugin page go to MUI_PAGE_WELCOME.

Please help me fix this.

Catching 'Skip' from plugin CurrentParentProc (Delphi):

  if (uMsg = WM_COMMAND) then
  begin
    //esc or skip button
    if (LOWORD(wParam) = 2) and (HIWORD(wParam) = BN_CLICKED) then
    begin
      //ShowMessage('here click skip and skip on ESC!!!');
      bStopPlugin := TRUE;
      bSkipActivation := TRUE;
    end;
//...
  end; 

Boolean bStopPlugin - it is a "flag" for translate messages:

  while bStopPlugin = FALSE do
  begin
    GetMessage(Msg, 0, 0, 0);
    if (not IsDialogMessage(PluginDialogFirstForm.Handle, Msg)) and (not IsDialogMessage(g_hwndParent, Msg))  then
    begin
      TranslateMessage(Msg);
      DispatchMessage(Msg);
    end;
  end; 
After, bSkipActivation - it is flag for skip. Also, I'm tried push 'next' in this statement, but - no luck.

    if bSkipActivation = TRUE then
    begin
      //NSIS_PushString_Ansi('next');
      SetWindowLongPtr(g_hwndParent, SizeOf(LRESULT), Longint(parentOriginalWndproc));
      Exit;
    end; 

Sorry for my English. Help me, please.
Anders#
The steps
But, if I try to click on 'Skip', after click on the 'Back' button - plugin page go to MUI_PAGE_WELCOME.
are unclear to me, please describe in more detail.

Are you eating the WM_COMMAND message in your subclass?

Post the WM_NOTIFY_OUTER_NEXT message to hwndParent with wParam=1 to go to the next page.
sfx09#
Originally Posted by Anders View Post
The steps are unclear to me, please describe in more detail.

Are you eating the WM_COMMAND message in your subclass?
Yes. In my procedure, where creating delphi-form, I wrote this:

  PluginDialogFirstForm := TPluginDialogFirstForm.CreateParented(g_hwndParent);
  parentOriginalWndproc := TFNWndProc(SetWindowLongPtr(g_hwndParent, SizeOf(LRESULT), Longint(@CurrentParentProc)));
  SendMessage(g_hwndParent, WM_NOTIFY_CUSTOM_READY, PluginDialogFirstForm.Handle, 0);
  PluginDialogFirstForm.Show; 
  while bStopPlugin = FALSE do
  begin
    GetMessage(Msg, 0, 0, 0);
    if (not IsDialogMessage(PluginDialogFirstForm.Handle, Msg)) and (not IsDialogMessage(g_hwndParent, Msg))  then
    begin
      TranslateMessage(Msg);
      DispatchMessage(Msg);
    end;
  end;
  if bStopPlugin = TRUE then
  begin
    PluginDialogFirstForm.Close;
    PluginDialogFirstForm.Free;
    if bSkipActivation = TRUE then
    begin
      //NSIS_PushString_Ansi('next');
      SetWindowLongPtr(g_hwndParent, SizeOf(LRESULT), Longint(parentOriginalWndproc));
      ShowMessage('bSkipActivation!');
      Exit;
    end;
    if bCancelClk = TRUE then
    begin
      NSIS_PushString_Ansi('cancel');
      Halt(0);
    end;
    if bBackClk = TRUE then
    begin
      //NSIS_PushString_Ansi('back');
      SetWindowLongPtr(g_hwndParent, SizeOf(LRESULT), Longint(parentOriginalWndproc));
      Exit;
    end;
    if bNextClk = TRUE then
    begin
        PluginDialogFirstForm.Hide;
        PluginDialogSecondForm.Show;
    end;
  end; 
It's CurrentParentProc full code for plugin:

function CurrentParentProc(hwnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
  wPar: LongInt;
begin
    if (uMsg = UINT(WM_NOTIFY_OUTER_NEXT)) then   //1032
    begin
      wPar := LongInt(wParam);
      //
      if (wPar = 120) then
      begin
        bCancelClk := TRUE;
        bStopPlugin := TRUE;
        //MessageBox(hwnd, PChar('exit'), PChar('-'), MB_OK);
      end;
      if (wPar = -1) then
      begin
        // MessageBox(hwnd, PChar('back'), PChar('-'), MB_OK);
        bBackClk := TRUE;
        bStopPlugin := TRUE;
      end;
      if (wPar = 1) then  //next
      begin
        bNextClk := TRUE;
        bStopPlugin := TRUE;
      end;
    end
    else if (uMsg = UINT(16)) then   //wm_close (X button)
    begin
      bExitNow := TRUE;
    end
    else if (uMsg = WM_COMMAND) then
    begin
      //esc or skip button
      if (LOWORD(wParam) = 2) and (HIWORD(wParam) = BN_CLICKED) and (bExitNow = FALSE) then
      begin
        //ShowMessage('here click skip and skip on ESC!!!');
        bStopPlugin := TRUE;
        bSkipActivation := TRUE;
        //SendMessage(g_hWndParent, WM_NOTIFY_OUTER_NEXT, 1, 0);
        Exit(0);
      end;
      bExitNow := FALSE;
    end;
  Result := CallWindowProc(parentOriginalWndproc, hWnd, uMsg, wParam, lParam);
end; 

Originally Posted by Anders View Post
Post the WM_NOTIFY_OUTER_NEXT message to hwndParent with wParam=1 to go to the next page.
Yes, i try this: SendMessage(g_hWndParent, WM_NOTIFY_OUTER_NEXT, 1, 0);
But, plugin go to the next Delphi-form (9 forms now in plugin), not next page installer (I need to skip all plugin work).

My code work normal, if I clicked on the 'Next' before clicking on 'Skip' (we go to the next NSIS-page). But, if I clicked on the 'Back' (it need to navigate between Delphi-forms) before clicking on 'Skip' - skipping go to previous NSIS-page.

So, if I send SendMessage(g_hWndParent, WM_NOTIFY_OUTER_NEXT, 1, 0); - I stay on same form (if I click 'Back' before 'Skip').
If I send SendMessage(g_hWndParent, WM_NOTIFY_OUTER_NEXT, 2, 0); - I goto second plugin-form, etc.

IMHO, it's not normal. Sorry, maybe I doing something wrong, but normal Delphi-source for plugin with GUI and more than one form, I can't find. =(

If such a plugin-source exists, maybe someone send me link. =)
sfx09#
Originally Posted by Anders View Post
Multiple pages are usually implemented with multiple "Page Custom xyz" instructions.
I need to exchange variables (and other data structures) between different modules/forms. So, the solution to multiply the pages will not work for me. The plugin really big.

But your answer about WM_NOTIFY_OUTER_NEXT working now (in other code place):

    if bSkipActivation = TRUE then
    begin
      SetWindowLongPtr(g_hwndParent, SizeOf(LRESULT), Longint(parentOriginalWndproc));
      SendMessage(g_hWndParent, WM_NOTIFY_OUTER_NEXT, 1, 0);
      Exit;
    end; 
Big thanks for help! 👍

After all, I decided to combine all forms into one, and use the Delphi-component TPageControl to separate the user interface. I want to do this in order to avoid potential problems in the future. Try it afternoon. Thanks!
sfx09#
Originally Posted by sfx09 View Post
After all, I decided to combine all forms into one, and use the Delphi-component TPageControl to separate the user interface. I want to do this in order to avoid potential problems in the future. Try it afternoon. Thanks!
So, using TPageControl in this task turned out even more difficult (for subclassing). But, my plugin is normal work with many forms now (however, I had to correct the last IF-constructions in procedures with "else if"). =) I hope, in the future too.