65.9K
CodeProject 正在变化。 阅读更多。
Home

CFormatDriveDialog - undocumented SHFormatDrive API函数的包装类

starIconstarIconstarIconstarIconstarIcon

5.00/5 (20投票s)

2002年8月28日

3分钟阅读

viewsIcon

195403

downloadIcon

3040

SHFormatDrive 的包装类(仅 XP/2K)。修正了 KB 文章 Q173688 中的一些错误

概述

这个类基本上会显示 Windows 磁盘格式化对话框。 你可能会认为它现在已经成为公共对话框的一部分了。 更糟糕的是,KB 文章 Q173688 中的某些信息现在对于 Windows XP 和 Windows 2000 来说是不正确的。 我推测 KB 文章是在 9x 时代编写的,他们忘记稍后删除或更新它。 让我感到困惑的是,KB 文章指出其中的信息适用于 XP 和 2K。 我遇到的第一个震惊是发现快速格式化选项的行为与 KB 文章中的描述完全相反。 此外,创建系统盘选项甚至无法正常工作。 无论如何,我编写了一个类 - CFormatDriveDialog,它基本上为您包装了这些东西。 我坚持使用 MS 推荐的常量定义(如果它们有效),但在其他情况下,我要么丢弃它们,要么添加自己的定义。

强烈警告

KB 文章 Q173688 中的信息部分不正确。 如果您打算在此类基础上构建,请不要盲目地遵循它。 另请注意,此类应仅在 Win2K/XP 系统上使用。 对于较旧的操作系统版本(如 9x 和 ME),应遵循 KB 文章。

类参考

这里只有一个公共方法(当然,除了无参数构造函数)。

DoModal

int CFormatDriveDialog::DoModal(HWND hWnd, UINT Drive, bool bQuickFormat, LPCTSTR vol_label);

  • hWnd - 对话框父窗口的窗口句柄。不能为 NULL
  • Drive - 驱动器代码(0 表示 A,1 表示 B,2 表示 C 等)我已经定义了诸如 DRIVEADRIVEBDRIVEC 等常量,您可以代替原始数字使用它们。它们在头文件中定义。
  • bQuickFormat - 如果 true,则默认情况下选中“快速格式化”复选框。
  • vol_label - 要使用的卷标的默认值。

返回值

如果成功完成格式化,则返回 IDOK;如果格式化操作被取消或发生某些错误,则返回 IDCANCEL

示例用法

void Cnish_testDlg::OnBnClickedButton1()
{
    UpdateData(true);
    CFormatDriveDialog dlg;
    int d=dlg.DoModal(AfxGetMainWnd()->m_hWnd,DRIVEA,
        bQuickFormat,m_vollab);
    if(d==IDOK)
        MessageBox("yeah"); 
}

技术细节

我们从 shell32.dll 调用 SHFormatDrive 函数。 我使用 LoadLibrary 加载 shell32.dll,然后调用 GetProcAddress 来获取 SHFormatDrive 的地址。 我还使用 SetWindowsHookEx 设置 CBT 钩子,因为我们需要设置卷标。 钩子过程调用 EnumChildWindows,当我们遇到具有“Edit”类的子窗口时,我们就知道这是卷标编辑框,因为这是对话框中唯一的编辑框。 有关完整详细信息,请参阅源代码。 下面给出了一个代码片段,其中包含实际源代码中未找到的注释。

int CFormatDriveDialog::DoModal(...)
{

    //...

    // Function pointer to hold SHFormatDrive
    FMTDRIVEFUNC* pshfd;

    // Load the dll
    HMODULE hMod = LoadLibrary("shell32.dll");

    // Chk for error - just in case
    if(hMod)
    {
        // Assign function pointer
        pshfd = reinterpret_cast<FMTDRIVEFUNC*>
            (GetProcAddress(hMod,"SHFormatDrive"));

        // Set a WH_CBT hook
        m_hHook = SetWindowsHookEx(WH_CBT,CBTProc,
            AfxGetApp()->m_hInstance,AfxGetApp()->m_nThreadID);

        // Call the function via the function pointer
        rv = ((*pshfd)(hWnd,Drive,SHFMT_ID_DEFAULT,Options)==
            SHFMT_FMTSUCCESS) ? IDOK : IDCANCEL;

        // Free the dll
        FreeLibrary(hMod);
    }
    
    //...
}

LRESULT CALLBACK CFormatDriveDialog::CBTProc(...)
{
    if (nCode == HCBT_ACTIVATE )
    { 
        // Get handle of Format dialog
        HWND hWnd = reinterpret_cast<HWND>(wParam);

        // Enumerate all child windows to get 
        // volume label the edit box
        EnumChildWindows(hWnd,EnumChildProc,NULL); 

        // Finished our need for the hook
        UnhookWindowsHookEx(m_hHook);
        CFormatDriveDialog::m_hHook = NULL; 
    }
    return FALSE;
}

BOOL CALLBACK CFormatDriveDialog::EnumChildProc(...)
{ 
    char buff[256];
    GetClassName(hwnd,buff,255);

    // The vol label edit box is the only edit control
    if(strcmp(buff,"Edit")==0)
    {
        SetWindowText(hwnd,m_vol_label);
        return FALSE;
    }
    return TRUE;
}

结论

上述 KB 文章中提到了几个返回代码和选项代码。 但是,它们都没有按预期工作,其中一些根本不起作用。 此外,给定的快速格式化代码常量以完全相反的方式工作。 当然,我根据自己在 XP 专业版机器上尝试代码的结果来得出结论。 我还请 James T Johnson 在他的 XP 专业版机器上部分测试了它,并请 Smitha(Tweety) 在她的 Windows 2000 专业版机器上测试了它。 但是我不知道这个类在未经测试的带有或不带有服务包的操作系统版本上将如何工作。

© . All rights reserved.