ちょっと発展: Vista 専用ダイアログを使う ~ TaskDialog
C/C++ を使って Windows プログラミングを行う醍醐味のひとつは、なんといっても最新の API を利用可能であることでしょう。 Windows API は基本的に最初に C/C++ で作られ、その上に .NET Framework や MFC などのラッパーがかぶせられます。 Windows API さえ発表されれば、中間のフレームワークがアップデートされるのを待つ必要なく、また PInvoke 等、独自に工夫して API を呼び出すまでも無く、 最も簡単にダイレクトに API を呼び出せます。
ここでは Windows Vista から利用可能な、TaskDialog を使って、Windows Vista から使えるようになった新しいルックアンドフィールのメッセージボックスを表示してみましょう。
ここでは TaskDialog を利用して以下のようにします。 TaskDialog はただのメッセージボックスの代わりとなる関数ではなく、もっと多機能な関数です。 ここでは前回ご紹介した MessageBox 関数と同等になるようにパラメータを選んでいます。
#include <windows.h> #include <commctrl.h> int WINAPI WinMain ( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { int n = 0; TaskDialog( NULL, hInstance, L"Hello", L"Hello, world!", L"It's very nice to meet you! I hope to see you again soon in Japanese.", TDCBF_OK_BUTTON, TD_INFORMATION_ICON, &n ); return 0; }
この結果、以下のようなダイアログが表示されます。
先ほどの MessageBox によるメッセージボックスと比べてみると、表示が異なることがわかるでしょう。
makefile は以下の通りです。TaskDialog は user32.lib ではなく、comctl32.lib とリンクすることに注意してください。
TARGETNAME=helloworld
OUTDIR=.\chk
LINK32=link.exe
ALL : "$(OUTDIR)\$(TARGETNAME).exe"
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
# compile
CPP_PROJ=\
/O1\
/nologo\
/W4\
/Fo"$(OUTDIR)\\"\
/Fd"$(OUTDIR)\\"\
/c\
/Zi\
/DUNICODE\
/D_UNICODE\
/D_WIN32_WINNT=0x0600
LINK32_FLAGS=\
comctl32.lib\
/nologo\
/subsystem:windows\
/pdb:"$(OUTDIR)\$(TARGETNAME).pdb"\
/out:"$(OUTDIR)\$(TARGETNAME).exe"\
/DEBUG
LINK32_OBJS= \
"$(OUTDIR)\$(TARGETNAME).obj"
"$(OUTDIR)\$(TARGETNAME).exe" : "$(OUTDIR)" $(LINK32_OBJS)
$(LINK32) $(LINK32_FLAGS) $(LINK32_OBJS)
.cpp{$(OUTDIR)}.obj:
$(CPP) $(CPP_PROJ) $<
さらに、TaskDialog のように Vista 以上のバージョンを必要とする API を利用する場合は、_WIN32_WINNT 定数を 0x0600 以上に設定しなければなりません。
ここまでで nmake するとビルドできるはずです。
次の内容を、helloworld.exe.manifest という名前で、helloworld.exe と同じディレクトリにおきます。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <description>helloworld</description> <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="microsoft.windows.common-controls" version="6.0.0.0" processorArchitecture="x86" publicKeyToken="6595b64144ccf1df" language="*" /> </dependentAssembly> </dependency> </assembly>
以上で正しく helloworld.exe が実行可能となるはずです。
補足: マニフェストファイルを置くのは、コモンコントロールのバージョン6 以上を指定するためです。 今回必要としているバージョンと異なる DLL を読み込んだ場合は次のエラーが発生します。
この時のスタックは次の通りでした。 確かにコモンコントロールのバージョンは 6 以上ではない、 5.82 が読み込まれています。
0:000> lmvm COMCTL32
start end module name
73600000 73685000 COMCTL32 (deferred)
Image path: C:\Windows\WinSxS\x86_microsoft
.windows.common-controls_6595b64144ccf1df_5.82.6001.18000_none_886786f450a74a05\COMCTL32.dll
Image name: COMCTL32.dll
Timestamp: Fri Jan 18 23:26:33 2008 (4791A629)
CheckSum: 00086963
ImageSize: 00085000
File version: 5.82.6001.18000
Product version: 6.0.6001.18000
File flags: 0 (Mask 3F)
File OS: 40004 NT Win32
File type: 2.0 Dll
File date: 00000000.00000000
Translations: 0409.04b0
CompanyName: Microsoft Corporation
ProductName: MicrosoftR WindowsR Operating System
InternalName: COMCTL32
OriginalFilename: COMCTL32.DLL
ProductVersion: 6.0.6001.18000
FileVersion: 5.82 (longhorn_rtm.080118-1840)
FileDescription: Common Controls Library
LegalCopyright: c Microsoft Corporation. All rights reserved.
以下のスタックとモジュール情報は正しく動作しているときのものです。 確かにバージョン6が使用されています。
0:000> kbn 100
# ChildEBP RetAddr Args to Child
00 0012fbb0 77039244 762ec3e4 00000002 0012fc04 ntdll!KiFastSystemCallRet
01 0012fbb4 762ec3e4 00000002 0012fc04 00000001 ntdll!ZwWaitForMultipleObjects+0xc
02 0012fc50 75ea0208 0012fc04 0012fc78 00000000 kernel32!WaitForMultipleObjectsEx+0x11d
03 0012fca4 7489161e 00000030 0012fcd8 ffffffff USER32!RealMsgWaitForMultipleObjectsEx+0x13c
04 0012fcc4 748929b0 000024ff ffffffff 00000000 DUser!CoreSC::Wait+0x59
05 0012fcec 7489294f 000024ff 00000000 0012fd18 DUser!CoreSC::WaitMessage+0x54
06 0012fcfc 75e8b0da 000024ff 00000000 00000000 DUser!MphWaitMessageEx+0x22
07 0012fd18 770399ce 0012fd30 00000008 0012ff78 USER32!__ClientWaitMessageExMPH+0x1e
08 0012fd34 75ea0dde 75e8b0b2 00000000 00000000 ntdll!KiUserCallbackDispatcher+0x2e
09 0012fd38 75e8b0b2 00000000 00000000 00000000 USER32!NtUserWaitMessage+0xc
0a 0012fd6c 75e8bcda 00650f12 00000000 00000001 USER32!DialogBox2+0x202
0b 0012fd94 75e8bd1c 745c0000 0023f700 00000000 USER32!InternalDialogBox+0xd0
0c 0012fdb4 75e8bd40 745c0000 0023f700 00000000 USER32!DialogBoxIndirectParamAorW+0x37
0d 0012fdd4 74639b94 745c0000 0023f700 00000000 USER32!DialogBoxIndirectParamW+0x1b
0e 0012fdf8 74639b24 745c0000 0023f700 00000000 COMCTL32!SHFusionDialogBoxIndirectParam+0x2d
0f 0012fe34 746a0c9a 0012fe68 0012fef4 00000000 COMCTL32!CTaskDialog::Show+0x10a
10 0012fecc 0040103c 00000000 00400000 00417a5c COMCTL32!TaskDialog+0x7e
11 0012fef8 004011d7 00400000 00000000 002326fe helloworld!WinMain+0x2d
12 0012ff88 762e4911 7ffdf000 0012ffd4 7701e4b6 helloworld!__tmainCRTStartup+0x113
13 0012ff94 7701e4b6 7ffdf000 6bf5ea88 00000000 kernel32!BaseThreadInitThunk+0xe
14 0012ffd4 7701e489 00401242 7ffdf000 00000000 ntdll!__RtlUserThreadStart+0x23
15 0012ffec 00000000 00401242 7ffdf000 00000000 ntdll!_RtlUserThreadStart+0x1b
0:000> lmvm COMCTL32
start end module name
745c0000 7475e000 COMCTL32 (pdb symbols)
C:\websymbols\comctl32.pdb\B07CB25578964646BF1423C7A4B5CB9D2\comctl32.pdb
Loaded symbol image file:
C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.6001
.18000_none_5cdbaa5a083979cc\COMCTL32.dll
Image path:
C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.6001
.18000_none_5cdbaa5a083979cc\COMCTL32.dll
Image name: COMCTL32.dll
Timestamp: Fri Jan 18 23:31:30 2008 (4791A752)
CheckSum: 001A2D0F
ImageSize: 0019E000
File version: 6.10.6001.18000
Product version: 6.0.6001.18000
File flags: 0 (Mask 3F)
File OS: 40004 NT Win32
File type: 2.0 Dll
File date: 00000000.00000000
Translations: 0409.04b0
CompanyName: Microsoft Corporation
ProductName: MicrosoftR WindowsR Operating System
InternalName: comctl32
OriginalFilename: comctl32.DLL
ProductVersion: 6.0.6001.18000
FileVersion: 6.10 (longhorn_rtm.080118-1840)
FileDescription: User Experience Controls Library
LegalCopyright: c Microsoft Corporation. All rights reserved.
0:000>