You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Win32API Wizard97中PropSheet_SetWizButtons函数失效求助

Win32API向导按钮无法切换问题求助

我正在用C语言学习Win32API,给应用添加向导功能,这是首次实现该功能,代码中肯定存在多处问题。参照MSDN网站的示例与说明完成了实现,但向导按钮无法切换,点击最后一页的Next无任何反应,仅能通过Cancel按钮关闭向导,恳请各位提供帮助!

#include <Windows.h>
#include <WinUser.h>
#include <richedit.h>
#include <prsht.h>
#include <commctrl.h>
#include "Resource.h"

//declarations
BOOL CALLBACK PrpWelcomeProc(HWND hDialog, UINT Message, WPARAM wParam, LPARAM lParam);
BOOL CALLBACK PrpEnvironmentVarsProc(HWND hDialog, UINT Message, WPARAM wParam, LPARAM lParam);
BOOL CALLBACK PrpToolChainVarsProc(HWND hDialog, UINT Message, WPARAM wParam, LPARAM lParam);
BOOL CALLBACK PrpEditorBehaviorProc(HWND hDialog, UINT Message, WPARAM wParam, LPARAM lParam);
BOOL CALLBACK PrpFinishProc(HWND hDialog, UINT Message, WPARAM wParam, LPARAM lParam);

int CreateProjectDialog(HWND Parent)
{
    HINSTANCE hInstance = GetModuleHandle(NULL);
    PROPSHEETPAGE psp = {sizeof (psp)};
    HPROPSHEETPAGE hPrP[5];

    // Setup the Welcome page
    psp.hInstance = hInstance;
    psp.dwFlags = PSP_HIDEHEADER;
    psp.pszTemplate = MAKEINTRESOURCE(IDD_PROPPAGE_LARGE_WELCOME);
    psp.pfnDlgProc = PrpWelcomeProc;
    psp.lParam = (LPARAM)NULL;
    hPrP[0] = CreatePropertySheetPage(&psp);

    // Setup the Environment Variables page
    psp.dwFlags =  PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
    psp.pszHeaderTitle = TEXT("Environment Variables");
    psp.pszHeaderSubTitle = TEXT("Use these options to setup the default environment for your OS    project.");
    psp.pszTemplate = MAKEINTRESOURCE(IDD_FORMVIEW_ENV_VARIABLES);
    psp.pfnDlgProc = PrpEnvironmentVarsProc;
    psp.lParam = (LPARAM)NULL;

    hPrP[1] = CreatePropertySheetPage(&psp);

    // Setup the Toolchain Options page
    psp.pszHeaderTitle = TEXT("Toolchain Settings");
    psp.pszHeaderSubTitle = TEXT("Use these options to setup your toolchain.");
    psp.pszTemplate = MAKEINTRESOURCE(IDD_PROPPAGE_LARGE);
    psp.pfnDlgProc = PrpToolChainVarsProc;
    psp.lParam = (LPARAM)NULL;

    hPrP[2] = CreatePropertySheetPage(&psp);

    // Setup the Editor Behavior page
    psp.pszHeaderTitle = TEXT("Editor Behavior");
    psp.pszHeaderSubTitle = TEXT("Use these options to customize the editor.");
    psp.pszTemplate = MAKEINTRESOURCE(IDD_PROPPAGE_LARGE_EDITOR);
    psp.pfnDlgProc = PrpEditorBehaviorProc;
    psp.lParam = (LPARAM)NULL;

    hPrP[3] = CreatePropertySheetPage(&psp);

    // Setup the Finish Page
    psp.dwFlags = PSP_HIDEHEADER;
    psp.pszHeaderTitle = NULL;
    psp.pszHeaderSubTitle = NULL;
    psp.pszTemplate = MAKEINTRESOURCE(IDD_PROPPAGE_FINISH);
    psp.pfnDlgProc = PrpFinishProc;
    psp.lParam = (LPARAM)NULL;

    hPrP[4] = CreatePropertySheetPage(&psp);

    // Setup the Propage Header to define the Wizard
    // The Watermark Bitmap and the Header Bitmap need to be created

    PROPSHEETHEADER pHeader = { sizeof(pHeader) };
    pHeader.dwFlags = PSH_WIZARD97 | PSH_WATERMARK;
    pHeader.hInstance = hInstance;
    pHeader.hwndParent = Parent;
    pHeader.nPages = &psp;
    pHeader.nStartPage = 0;
    pHeader.nPages = 5;
    pHeader.pszbmWatermark = MAKEINTRESOURCE(IDB_BITMAP1);
    pHeader.phpage = hPrP;

    // Launch the Wizard
    PropertySheet(&pHeader);

    return 0;
}

//Dialog Procedures for all of the Dialogs in the Create Project Wizard


 BOOL CALLBACK PrpWelcomeProc(HWND hDialog, UINT Message, WPARAM wParam, LPARAM lParam)
{
LPNMHDR pnmh = (LPNMHDR)lParam;

switch (Message)
{
case WM_INITDIALOG:

    
return FALSE;

case WM_NOTIFY:
    

    switch (pnmh->code)
    {
    case PSN_SETACTIVE:
    PropSheet_SetWizButtons(hDialog, PSWIZB_NEXT);
    return FALSE;
    }

}

return  FALSE;
}

BOOL CALLBACK PrpEnvironmentVarsProc(HWND hDialog, UINT Message, WPARAM wParam, LPARAM lParam)
{
LPNMHDR pnmh = (LPNMHDR)lParam;
switch (Message)
{
case WM_INITDIALOG:
    
return FALSE;


case WM_NOTIFY:
    

switch (pnmh->code)
{
case PSN_SETACTIVE:
PropSheet_SetWizButtons(hDialog, PSWIZB_NEXT | PSWIZB_BACK | PSWIZB_CANCEL);
return FALSE;


    }
}
return FALSE;
}
  BOOL CALLBACK PrpToolChainVarsProc(HWND hDialog, UINT Message, WPARAM wParam, LPARAM lParam)
  {
LPNMHDR pnmh = (LPNMHDR)lParam;

switch (Message)
{
case WM_INITDIALOG:
    
    return FALSE;

case WM_NOTIFY:
    

    switch (pnmh->code)
    {
    case PSN_SETACTIVE:
        PropSheet_SetWizButtons(hDialog, PSWIZB_NEXT | PSWIZB_BACK | PSWIZB_CANCEL);
        return FALSE;


    }
}

return FALSE;
}

BOOL CALLBACK PrpEditorBehaviorProc(HWND hDialog, UINT Message, WPARAM wParam, LPARAM lParam)
{
LPNMHDR pnmh = (LPNMHDR)lParam;

switch (Message)
{
case WM_INITDIALOG:

    return FALSE;


case WM_NOTIFY:
    ;

    switch (pnmh->code)
    {
    case PSN_SETACTIVE:
        PropSheet_SetWizButtons(hDialog, PSWIZB_NEXT | PSWIZB_BACK | PSWIZB_CANCEL);
        return FALSE;


    }

}
return FALSE;
}

BOOL CALLBACK PrpFinishProc(HWND hDialog, UINT Message, WPARAM wParam, LPARAM lParam)
{
LPNMHDR pnmh = (LPNMHDR)lParam;

switch (Message)
{
case WM_INITDIALOG:
    
    return FALSE;

case WM_NOTIFY:
    

    switch (pnmh->code)
    {
     case PSN_SETACTIVE:
        PropSheet_SetWizButtons(hDialog, PSWIZB_BACK | PSWIZB_CANCEL | PSWIZB_FINISH);
        PropSheet_SetFinishText(hDialog, TEXT("Finish"));
        return FALSE;


    }

case WM_DESTROY:
    return FALSE;
}
return FALSE;
}

问题分析与修复方案

1. PROPSHEETHEADER初始化错误

你在设置pHeader时错误地写了pHeader.nPages = &psp;,这行代码会将页面数量变量赋值为一个指针地址,后续虽然覆盖为5,但属于无效操作。直接移除这行错误代码即可:

PROPSHEETHEADER pHeader = { sizeof(pHeader) };
pHeader.dwFlags = PSH_WIZARD97 | PSH_WATERMARK;
pHeader.hInstance = hInstance;
pHeader.hwndParent = Parent;
// 移除这行错误代码:pHeader.nPages = &psp;
pHeader.nStartPage = 0;
pHeader.nPages = 5;
pHeader.pszbmWatermark = MAKEINTRESOURCE(IDB_BITMAP1);
pHeader.phpage = hPrP;

2. 对话框过程返回值错误

处理PSN_SETACTIVE通知时,你返回了FALSE,但根据Win32API规范,返回FALSE会阻止页面激活,导致按钮切换失效。所有页面的PSN_SETACTIVE分支都需要改为返回TRUE,例如:

case PSN_SETACTIVE:
    PropSheet_SetWizButtons(hDialog, PSWIZB_NEXT);
    return TRUE; // 从FALSE改为TRUE

3. Finish页添加完成逻辑

Finish页需要处理PSN_WIZFINISH通知,允许向导正常关闭:

BOOL CALLBACK PrpFinishProc(HWND hDialog, UINT Message, WPARAM wParam, LPARAM lParam)
{
    LPNMHDR pnmh = (LPNMHDR)lParam;

    switch (Message)
    {
    case WM_INITDIALOG:
        return FALSE;

    case WM_NOTIFY:
        switch (pnmh->code)
        {
        case PSN_SETACTIVE:
            PropSheet_SetWizButtons(hDialog, PSWIZB_BACK | PSWIZB_CANCEL | PSWIZB_FINISH);
            PropSheet_SetFinishText(hDialog, TEXT("Finish"));
            return TRUE; // 改为TRUE
        case PSN_WIZFINISH:
            // 可在此添加向导完成后的业务逻辑
            SetWindowLongPtr(hDialog, DWLP_MSGRESULT, 0); // 允许向导关闭
            return TRUE;
        }
        break;
    case WM_DESTROY:
        return FALSE;
    }
    return FALSE;
}

内容的提问来源于stack exchange,提问作者Dave B.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 13:15:55