ちょっと発展: 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;
}

この結果、以下のようなダイアログが表示されます。

TaskDialog によるメッセージボックス

先ほどの MessageBox によるメッセージボックスと比べてみると、表示が異なることがわかるでしょう。

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>

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 Web/DB プログラミング徹底解説