diff --git a/Contrib/InstallOptions/InstallerOptions.cpp b/Contrib/InstallOptions/InstallerOptions.cpp index a19ab545..2f78f78e 100644 --- a/Contrib/InstallOptions/InstallerOptions.cpp +++ b/Contrib/InstallOptions/InstallerOptions.cpp @@ -605,17 +605,27 @@ LRESULT WMCommandProc(HWND hWnd, UINT id, HWND hwndCtl, UINT codeNotify) { static void *lpWndProcOld; -static LRESULT CALLBACK ParentWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - if (message == WM_NOTIFY_OUTER_NEXT) - { - PostMessage(hConfigWindow,WM_USER+666,wParam,0); - } - return CallWindowProc((long (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long))lpWndProcOld,hwnd,message,wParam,lParam); -} - int g_is_cancel,g_is_back; +BOOL CALLBACK ParentWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + BOOL bRes; + if (message == WM_NOTIFY_OUTER_NEXT && wParam == 1) + // Get the settings ready for the leave function verification + SaveSettings(); + bRes = CallWindowProc((long (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long))lpWndProcOld,hwnd,message,wParam,lParam); + if (message == WM_NOTIFY_OUTER_NEXT && !bRes) + { + // if leave function didn't abort (lRes != 0 in that case) + if (wParam == NOTIFY_BYE_BYE || wParam == -1 || ValidateFields()) { + if (wParam == -1) g_is_back++; + if (wParam == NOTIFY_BYE_BYE) g_is_cancel++; + g_done++; + PostMessage(hConfigWindow,WM_CLOSE,0,0); + } + } + return bRes; +} BOOL CALLBACK cfgDlgProc(HWND hwndDlg, UINT uMsg, @@ -625,15 +635,6 @@ BOOL CALLBACK cfgDlgProc(HWND hwndDlg, switch (uMsg) { HANDLE_MSG(hwndDlg, WM_COMMAND, WMCommandProc); - return 0; - case WM_USER+666: - if (wParam == NOTIFY_BYE_BYE || wParam == -1 || ValidateFields()) { - if (wParam == -1) g_is_back++; - if (wParam == NOTIFY_BYE_BYE) g_is_cancel++; - g_done++; - PostMessage(hwndDlg,WM_CLOSE,0,0); - } - break; case WM_CTLCOLORSTATIC: case WM_CTLCOLORDLG: SetBkMode((HDC)wParam, TRANSPARENT); @@ -962,7 +963,7 @@ int createCfgDlg() void showCfgDlg() { - lpWndProcOld = (void *) SetWindowLong(hMainWindow,GWL_WNDPROC,(long)ParentWndProc); + lpWndProcOld = (void *) SetWindowLong(hMainWindow,DWL_DLGPROC,(long)ParentWndProc); SendMessage(hMainWindow, WM_NOTIFY_CUSTOM_READY, 0, 0); ShowWindow(hConfigWindow, SW_SHOWNA); @@ -982,7 +983,7 @@ void showCfgDlg() if (!g_is_cancel) SaveSettings(); if (lpWndProcOld) - SetWindowLong(hMainWindow,GWL_WNDPROC,(long)lpWndProcOld); + SetWindowLong(hMainWindow,DWL_DLGPROC,(long)lpWndProcOld); DestroyWindow(hConfigWindow); if (was_ok_enabled) EnableWindow(hNextButton,0); SetWindowText(hCancelButton,old_cancel); diff --git a/Contrib/InstallOptions/test.nsi b/Contrib/InstallOptions/test.nsi index 55a1a44c..22958d97 100644 --- a/Contrib/InstallOptions/test.nsi +++ b/Contrib/InstallOptions/test.nsi @@ -10,6 +10,9 @@ Name "InstallOptions Test" ;The file to write OutFile "Test.exe" +; Show install details +ShowInstDetails show + ;Things that need to be extracted on startup (keep these lines before any File command!) ;Only useful for BZIP2 compression ;Use ReserveFile for your own InstallOptions INI files too! @@ -18,7 +21,7 @@ ReserveFile "${NSISDIR}\Plugins\InstallOptions.dll" ReserveFile "test.ini" ;Order of pages -Page custom SetCustom ": Testing InstallOptions" ;Custom page. InstallOptions gets called in SetCustom. +Page custom SetCustom VerifyCustom ": Testing InstallOptions" ;Custom page. InstallOptions gets called in SetCustom. Page instfiles Section "Components" @@ -26,15 +29,15 @@ Section "Components" ;Get Install Options dialog user input ReadINIStr ${TEMP1} "$PLUGINSDIR\test.ini" "Field 2" "State" - MessageBox MB_OK "Install X=${TEMP1}" + DetailPrint "Install X=${TEMP1}" ReadINIStr ${TEMP1} "$PLUGINSDIR\test.ini" "Field 3" "State" - MessageBox MB_OK "Install Y=${TEMP1}" + DetailPrint "Install Y=${TEMP1}" ReadINIStr ${TEMP1} "$PLUGINSDIR\test.ini" "Field 4" "State" - MessageBox MB_OK "Install Z=${TEMP1}" + DetailPrint "Install Z=${TEMP1}" ReadINIStr ${TEMP1} "$PLUGINSDIR\test.ini" "Field 5" "State" - MessageBox MB_OK "File=${TEMP1}" + DetailPrint "File=${TEMP1}" ReadINIStr ${TEMP1} "$PLUGINSDIR\test.ini" "Field 6" "State" - MessageBox MB_OK "Dir=${TEMP1}" + DetailPrint "Dir=${TEMP1}" SectionEnd @@ -59,4 +62,16 @@ Function SetCustom Pop ${TEMP1} +FunctionEnd + +Function VerifyCustom + ReadINIStr ${TEMP1} "$PLUGINSDIR\test.ini" "Field 2" "State" + StrCmp ${TEMP1} 1 done + ReadINIStr ${TEMP1} "$PLUGINSDIR\test.ini" "Field 3" "State" + StrCmp ${TEMP1} 1 done + ReadINIStr ${TEMP1} "$PLUGINSDIR\test.ini" "Field 4" "State" + StrCmp ${TEMP1} 1 done + MessageBox MB_ICONSTOP|MB_OK "You must select at least one install option!" + Abort + done: FunctionEnd \ No newline at end of file diff --git a/Contrib/StartMenu/StartMenu.c b/Contrib/StartMenu/StartMenu.c index ca73b2e5..f578c126 100644 --- a/Contrib/StartMenu/StartMenu.c +++ b/Contrib/StartMenu/StartMenu.c @@ -26,7 +26,7 @@ int noicon = 0; void *lpWndProcOld; BOOL CALLBACK dlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); -LRESULT CALLBACK ParentWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +BOOL CALLBACK ParentWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); void AddFolderFromReg(HKEY rootKey); void __declspec(dllexport) Select(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) @@ -91,7 +91,7 @@ void __declspec(dllexport) Select(HWND hwndParent, int string_size, char *variab } else { - lpWndProcOld = (void *) SetWindowLong(hwndParent, GWL_WNDPROC, (long) ParentWndProc); + lpWndProcOld = (void *) SetWindowLong(hwndParent, DWL_DLGPROC, (long) ParentWndProc); } while (!g_done) @@ -103,19 +103,21 @@ void __declspec(dllexport) Select(HWND hwndParent, int string_size, char *variab } DestroyWindow(hwStartMenuSelect); - SetWindowLong(hwndParent, GWL_WNDPROC, (long) lpWndProcOld); + SetWindowLong(hwndParent, DWL_DLGPROC, (long) lpWndProcOld); if (cw_vis) ShowWindow(hwChild, SW_SHOW); } } -static LRESULT CALLBACK ParentWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +static BOOL CALLBACK ParentWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { - if (message == WM_NOTIFY_OUTER_NEXT) + BOOL bRes = CallWindowProc((long (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long))lpWndProcOld,hwnd,message,wParam,lParam); + if (message == WM_NOTIFY_OUTER_NEXT && !bRes) { + // if leave function didn't abort (lRes != 0 in that case) PostMessage(hwStartMenuSelect,WM_USER+666,wParam,0); } - return CallWindowProc((long (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long))lpWndProcOld,hwnd,message,wParam,lParam); + return bRes; } #define ProgressiveSetWindowPos(hwWindow, x, cx, cy) \ diff --git a/Docs/src/pages.but b/Docs/src/pages.but index 3e6c39bb..7191634b 100644 --- a/Docs/src/pages.but +++ b/Docs/src/pages.but @@ -21,9 +21,9 @@ If you don't use any Page command the installer pages order will be just as in o \S{pagecallbacks} Callbacks -Each built-in page has three callback functions. The pre-function, the show-creation function and the leave-function. The pre-function is called right before the page is created, the show-function is called right after it is created and before it is showen so you can tweak its user interface with \R{createfont}{CreateFont}, \R{setstaticbkcolor}{SetStaticBkColor } and \R{sendmessage}{SendMessage}; the leave-function is called right after the user has pressed the next button and before the page is left. +Each built-in page has three callback functions. The pre-function, the show-creation function and the leave-function. The pre-function is called right before the page is created, the show-function is called right after it is created and before it is shown so you can tweak its user interface with \R{createfont}{CreateFont}, \R{setstaticbkcolor}{SetStaticBkColor } and \R{sendmessage}{SendMessage}; the leave-function is called right after the user has pressed the next button and before the page is left. -A custom page has only one callback function that creates it but unlike the built-in pages this function is mandatory. +A custom page has only two callback functions, one that creates it which is mandatory, and one leave-function that acts just like the leave-function for built-in pages. Use \R{abort}{Abort} from a built-in page's pre-function to skip the page, and from a built-in page's leave-function to stay in the page. @@ -59,12 +59,12 @@ Examples: \S{page} Page -\c ((custom [function] [caption]) | ((license|components|directory|instfiles) [pre_function] [show_function] [leave_function])) [define_if_last] +\c ((custom [creator_function] [leave_function] [caption]) | ((license|components|directory|instfiles) [pre_function] [show_function] [leave_function])) [define_if_last] Adds an installer page. See the above sections for more information about built-in versus custom pages and about callback functions. If define_if_last is specified, the parameter will be !defined if the page turns out to be the last page before a instfiles page. This helps you decide on dynamic scripts (such as the Modern UI script) what to put in this page's text, "click the install button to start installation" or "click next to continue" for example. \S{uninstpage} UninstPage -\c ((custom [function] [caption]) | ((uninstConfirm|instfiles) [pre_function] [show_function] [leave_function])) [define_if_last] +\c ((custom [creator_function] [leave_function] [caption]) | ((uninstConfirm|instfiles) [pre_function] [show_function] [leave_function])) [define_if_last] Adds an uninstaller page. See the above sections for more information about built-in versus custom pages and about callback functions. See Page for an explanation about define_if_last. \ No newline at end of file diff --git a/Plugins/InstallOptions.dll b/Plugins/InstallOptions.dll index e9047569..fa20a9ed 100644 Binary files a/Plugins/InstallOptions.dll and b/Plugins/InstallOptions.dll differ diff --git a/Plugins/StartMenu.dll b/Plugins/StartMenu.dll index f16bdb31..4f500fae 100644 Binary files a/Plugins/StartMenu.dll and b/Plugins/StartMenu.dll differ diff --git a/Source/build.cpp b/Source/build.cpp index 3d729ef2..5eeb43c5 100644 --- a/Source/build.cpp +++ b/Source/build.cpp @@ -1086,9 +1086,9 @@ int CEXEBuild::resolve_coderefs(const char *str) page *p=(page *)ubuild_pages.get(); int i = 0; while (i < build_uninst.common.num_pages) { - if (resolve_call_int("uninstall pages","pre-page function",p->prefunc,&p->prefunc)) return 1; - if (resolve_call_int("uninstall pages","show-page function",p->showfunc,&p->showfunc)) return 1; - if (resolve_call_int("uninstall pages","leave-page function",p->leavefunc,&p->leavefunc)) return 1; + if (resolve_call_int("uninstall pages","pre-page",p->prefunc,&p->prefunc)) return 1; + if (resolve_call_int("uninstall pages","show-page",p->showfunc,&p->showfunc)) return 1; + if (resolve_call_int("uninstall pages","leave-page",p->leavefunc,&p->leavefunc)) return 1; p++; i++; } diff --git a/Source/exehead/Ui.c b/Source/exehead/Ui.c index 49296f6a..1ccdf0cb 100644 --- a/Source/exehead/Ui.c +++ b/Source/exehead/Ui.c @@ -513,13 +513,13 @@ BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) this_page=g_inst_page+m_page; if (m_page>=0) { + // Call leave function. If Abort used don't move to the next page. + if (m_delta==1) if (ExecuteCodeSegment(this_page->leavefunc,NULL)) return 1; + // if the last page was a custom page, wait for it to finish by itself. // if it doesn't, it's a BAD plugin. // plugins should react to WM_NOTIFY_OUTER_NEXT. if (this_page->id<0) return 0; - - // Call leave function. If Abort used don't move to the next page. - if (m_delta==1) if (ExecuteCodeSegment(this_page->leavefunc,NULL)) return 0; } nextPage: diff --git a/Source/script.cpp b/Source/script.cpp index 0e84169b..27c184ca 100644 --- a/Source/script.cpp +++ b/Source/script.cpp @@ -618,13 +618,14 @@ int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, const char // a custom page switch (line.getnumtokens() - enable_last_page_cancel) { case 7: + PRINTHELP(); case 6: - ERROR_MSG("Error: custom page can not have more than the creator function.\n"); - return PS_ERROR; + lstrcpy(build_last_page_define, line.gettoken_str(5)); case 5: - lstrcpy(build_last_page_define, line.gettoken_str(4)); + p.caption = add_string_main(line.gettoken_str(4)); case 4: - p.caption = add_string_main(line.gettoken_str(3)); + if (*line.gettoken_str(3)) + p.leavefunc = ns_func.add(line.gettoken_str(3),0); case 3: if (*line.gettoken_str(2)) p.prefunc = ns_func.add(line.gettoken_str(2),0); @@ -678,8 +679,8 @@ int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, const char SCRIPT_MSG(" (%s:%s)", k?"pre":"creator", line.gettoken_str(2)); if (p.showfunc>=0 && k) SCRIPT_MSG(" (show:%s)", line.gettoken_str(3)); - if (p.leavefunc>=0 && k) - SCRIPT_MSG(" (leave:%s)", line.gettoken_str(4)); + if (p.leavefunc>=0) + SCRIPT_MSG(" (leave:%s)", line.gettoken_str(4-!k)); else if (p.caption && !k) SCRIPT_MSG(" (caption:%s)", line.gettoken_str(3)); #endif @@ -776,13 +777,19 @@ int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, const char // a custom page switch (line.getnumtokens() - uenable_last_page_cancel) { case 7: + PRINTHELP(); case 6: - ERROR_MSG("Error: custom page can not have more than the creator function.\n"); - return PS_ERROR; + lstrcpy(ubuild_last_page_define, line.gettoken_str(5)); case 5: - lstrcpy(ubuild_last_page_define, line.gettoken_str(4)); + p.caption = add_string_uninst(line.gettoken_str(4)); case 4: - p.caption = add_string_uninst(line.gettoken_str(3)); + if (*line.gettoken_str(3)) { + if (strnicmp(line.gettoken_str(3),"un.",3)) { + ERROR_MSG("\nError: uninstall function must have a un. prefix!\n"); + return PS_ERROR; + } + p.leavefunc = ns_func.add(line.gettoken_str(3),0); + } case 3: if (*line.gettoken_str(2)) { if (strnicmp(line.gettoken_str(2),"un.",3)) { @@ -822,8 +829,8 @@ int CEXEBuild::doCommand(int which_token, LineParser &line, FILE *fp, const char SCRIPT_MSG(" (%s:%s)", k?"pre":"creator", line.gettoken_str(2)); if (p.showfunc>=0 && k) SCRIPT_MSG(" (show:%s)", line.gettoken_str(3)); - if (p.leavefunc>=0 && k) - SCRIPT_MSG(" (leave:%s)", line.gettoken_str(4)); + if (p.leavefunc>=0) + SCRIPT_MSG(" (leave:%s)", line.gettoken_str(4-!k)); else if (p.caption && !k) SCRIPT_MSG(" (caption:%s)", line.gettoken_str(3)); #endif diff --git a/Source/tokens.cpp b/Source/tokens.cpp index 681b7484..58ba8082 100644 --- a/Source/tokens.cpp +++ b/Source/tokens.cpp @@ -108,7 +108,7 @@ static tokenType tokenlist[TOK__LAST] = {TOK_NAME,"Name",1,1,"[/LANG=lang_id] installer_name"}, {TOK_OUTFILE,"OutFile",1,0,"install_output.exe"}, #ifdef NSIS_SUPPORT_CODECALLBACKS -{TOK_PAGE,"Page",1,5,"((custom [function] [caption]) | ((license|components|directory|instfiles) [pre_function] [show_function] [leave_function])) [define_if_last]"}, +{TOK_PAGE,"Page",1,5,"((custom [creator_function] [leave_function] [caption]) | ((license|components|directory|instfiles) [pre_function] [show_function] [leave_function])) [define_if_last]"}, #else {TOK_PAGE,"Page",1,1,"license|components|directory|instfiles"}, #endif @@ -168,7 +168,7 @@ static tokenType tokenlist[TOK__LAST] = {TOK_UNINSTCAPTION,"UninstallCaption",1,1,"[/LANG=lang_id] uninstaller_caption"}, {TOK_UNINSTICON,"UninstallIcon",1,0,"icon_on_local_system.ico"}, #ifdef NSIS_SUPPORT_CODECALLBACKS -{TOK_UNINSTPAGE,"UninstPage",1,5,"((custom [function] [caption]) | ((uninstConfirm|instfiles) [pre_function] [show_function] [leave_function])) [define_if_last]"}, +{TOK_UNINSTPAGE,"UninstPage",1,5,"((custom [creator_function] [leave_function] [caption]) | ((uninstConfirm|instfiles) [pre_function] [show_function] [leave_function])) [define_if_last]"}, #else {TOK_UNINSTPAGE,"UninstPage",1,1,"uninstConfirm|instfiles"}, #endif