.NET Formアプリでの Win32 API 使用

解決


DD.  2006-01-20 00:27:59  No: 60377

DD.です。お世話になります。

非常に初歩的すぎるところでつまづいてしまっています。
.NET なプログラムは作成したことがないもので。。。

VC++2005 Express 使用ですが、リソースエディタがないけど手動で書くのはめんどくさいと、.NET Form アプリで作成してみようと思い立ちました。

「新規作成」→「Visual C++」→「Windows フォーム アプリケーション」からデフォルトのものにボタンを一つ追加し、

  System::Void button1_Click( System::Object^ sender, System::EventArgs^ e ) {
    MessageBox( GetActiveWindow(), "", "", MB_OK );
  }

Win32 API である MessageBox() を試しに一つ追加しました。

そしてコンパイラに

...\test17\Form1.h(149) : error C2872: 'MessageBox' : あいまいなシンボルです。
        'C:\Program Files\Microsoft Platform SDK\Include\winuser.h(7205) の可能性があります : int MessageBox(HWND,LPCTSTR,LPCTSTR,UINT)''
        または 'c:\windows\microsoft.net\framework\v2.0.50727\system.windows.forms.dll : System::Windows::Forms::MessageBox'

と、エラーを吐かれてしまいます。
エラーの通り、<windows.h>は include してるんですが。

Win32 API を使うのに .NET Form アプリだと何か必要な作業があるのでしょうか?

#根本的に的外れなこといってたら申し訳ないです


Blue  2006-01-20 00:38:23  No: 60378

とりあえず、
> Win32 API を使うのに .NET Form アプリだと何か必要な作業があるのでしょうか?
はないはずだと思いますが。。
http://www.atmarkit.co.jp/fdotnet/special/cppcli/cppcli_01.html
の「■C標準ライブラリとWin32 APIと.NET Frameworkクラス・ライブラリを呼び出す」

> または 'c:\windows\microsoft.net\framework\v2.0.50727\system.windows.forms.dll : System::Windows::Forms::MessageBox'
System::Windows::Forms が usingnamespace されていると
MessageBox というのが System::Windows::Forms::MessageBox と思っちゃっているんですね。
# CLRなら System::Windows::Forms::MessageBox を使うべきなんだと思うが。。。

名前が競合(?)するときになんか技があるかも。


Blue  2006-01-20 00:46:57  No: 60379

明に
#ifdef _UNICODE
    MessageBoxW( GetActiveWindow(), L"", L"", MB_OK );
#else
    MessageBoxA( GetActiveWindow(), "", "", MB_OK );
#endif
とすると動くかも。
(今環境がないので試せない)

他の API は使えないか確認してみてはどうでしょうか?


DD.  2006-01-20 00:50:56  No: 60380

Blueさん、ありがとうございます。<(_ _)>

>http://www.atmarkit.co.jp/fdotnet/special/cppcli/cppcli_01.html
>の「■C標準ライブラリとWin32 APIと.NET Frameworkクラス・ライブラリを呼び出す」
実はこの書き込みの前にちょうど読んだんです^^;

#pragma unmanaged なんかも試したんですけど、結果は同じでした。

>System::Windows::Forms が usingnamespace されていると
>MessageBox というのが System::Windows::Forms::MessageBox と思っちゃっているんですね。
なるほど。
MessageBox だけならば
System::Windows::Forms::MessageBox::Show() でいいかなぁと思うんですが
それ以外にも多々 Win32 API から同様なエラーが出てまして^^;

># CLRなら System::Windows::Forms::MessageBox を使うべきなんだと思うが。。。
orz


DD.  2006-01-20 00:57:09  No: 60381

>#ifdef _UNICODE
>    MessageBoxW( GetActiveWindow(), L"", L"", MB_OK );
>#else
>    MessageBoxA( GetActiveWindow(), "", "", MB_OK );
>#endif
>とすると動くかも。

実はあらかじめ

#undef UNICODE

と、していたり・・・

>他の API は使えないか確認してみてはどうでしょうか?
他 API でも同じでしたorz


DD.  2006-01-20 01:15:11  No: 60382

他ソースファイルをプロジェクトに追加しましてコンパイルしたところ(他 API 複数含む)エラー内容が少し変わりましたので報告致します。

app_cmp.obj : error LNK2028: 未解決のトークン (0A00004C) "extern "C" int __stdcall MessageBoxA(struct HWND__ *,char const *,char const *,unsigned int)" (?MessageBoxA@@$$J216YGHPAUHWND__@@PBD1I@Z) が関数 "private: bool __clrcall app_cmp::AppCmp::reg_open_key(char const *)" (?reg_open_key@AppCmp@app_cmp@@$$FAAM_NPBD@Z) で参照されました。

app_cmp.obj : error LNK2028: 未解決のトークン (0A000046) "extern "C" struct HWND__ * __stdcall GetActiveWindow(void)" (?GetActiveWindow@@$$J10YGPAUHWND__@@XZ) が関数 "public: int __clrcall app_cmp::AppCmp::open_cmp_file(void)" (?open_cmp_file@AppCmp@app_cmp@@$$FQAMHXZ) で参照されました。

他 API も同様のエラーになります。


kure  2006-01-20 01:47:37  No: 60383

::MessageBox(...);
でいかがでしょうか?

あと、未解決のトークン関連ですが
たしかExpressEditionでは初期設定でリンクするライブラリが
kernel32のみだったと思いますので、
user32やらの必要なものは自前でリンクするか
プロジェクトの設定に追加すれば解決できると思いますよ。


Blue  2006-01-20 01:53:12  No: 60384

あれ?

Visual C++ 2005 Express Edition と Microsoft Platform SDK を一緒に使う
http://www.microsoft.com/japan/msdn/vstudio/express/visualc/usingpsdk/
の設定をしてても、CLRプログラムのときは
> user32やらの必要なものは自前でリンクするか
> プロジェクトの設定に追加すれば解決できると思いますよ。
しないといけないのかなぁ?


DD.  2006-01-20 01:57:12  No: 60385

kuraさん、ありがとうございます。

>::MessageBox(...);
こいつはしてみたんですがだめでした。。。
:: まで入れればインテリセンスで参照はしてくれます。

>あと、未解決のトークン関連ですが
>たしかExpressEditionでは初期設定でリンクするライブラリが
>kernel32のみだったと思いますので、
>user32やらの必要なものは自前でリンクするか
>プロジェクトの設定に追加すれば解決できると思いますよ。
実は VC++2005 Express インストール時に対処済みであります<(_ _)>

ただの SDK プログラムであれば問題ないです。
.NET にするとダメなんです;;


DD.  2006-01-20 02:02:46  No: 60386

>Visual C++ 2005 Express Edition と Microsoft Platform SDK を一緒に使う
>http://www.microsoft.com/japan/msdn/vstudio/express/visualc/usingpsdk/
>の設定をしてても、CLRプログラムのときは
>> user32やらの必要なものは自前でリンクするか
>> プロジェクトの設定に追加すれば解決できると思いますよ。
>しないといけないのかなぁ?
の、時はなにか別に対処する必要があるんですかね。。。
PSDKのパスも確認済みです。


Toshi  2006-01-20 03:39:32  No: 60387

時間取れなくて全然見てないんですが、
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/vbcon/html/vbconadditionalsecurityconsiderationsinwindowsforms.asp
とかって参考になりませんか?


kure  2006-01-20 03:42:54  No: 60388

うーん・・・設定済みであれば大丈夫なはずですね・・・。

もしかしてこれかな?

http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/vccore/html/vcrefEECOMCompilation.asp

/clrコンパイルオプションが関連してそう・・・


Youhei  2006-01-20 03:56:36  No: 60389

Youheiです。

やってみましたけど出来ましたよ。

CLRのWindowsフォームアプリケーションのウィザードが作成したコードに
ボタンを一つ追加してイベントハンドラを作成。で、その後にコード追加。

//stdafx.h追加分
#include <windows.h>
#pragma comment(lib, "user32.lib")
//stdafx.h追加ここまで

//Form1.h追加分
System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
  ::MessageBox(reinterpret_cast<HWND>(this->Handle.ToInt32()), L"OK!", L"test", MB_OK);
}
//Form1.h追加ここまで

プロジェクトの設定は一切触ってません。

やってみて感じたCLRプロジェクトの注意点としては(既出含む)

  ・デフォルトでusing namespaceがゴソッと入っているので一部の名前がカブる。
    (MessageBoxとか。)

  ・ハンドルの受け渡しがめんどくさい(動いたけど調べてないので合ってるか不明。)。

  ・デフォルトでUNICODEビルドになっている。

ってところでしょうか。ご参考まで。


DD.  2006-01-20 04:18:53  No: 60390

様々な回答ありがとうございます。

現在、確認できる環境がありませんので、申し訳ないですが
また明日返答させてもらいます。

/clr オプションが怪しそう・・・


シャノン  2006-01-20 05:19:56  No: 60391

今回の現象とは逆になりますが、System::Windows::Forms::MessageBox を使おうとすると、#define されてるせいで、System::Windows::Forms::MessageBoxA/W になっちゃってコケるかもしれません。


Blue  2006-01-20 09:41:04  No: 60392

> user32やらの必要なものは自前でリンクするか
ということで
> #pragma comment(lib, "user32.lib")
または
プロジェクトの プロパティ ページ の リンカ の 入力 の 追加の依存ファイルに指定
がないとリンクエラーになりますね。

私の環境でも正常動作が確認できました。
(WindowsXpSP2Pro,Visual C++ 2005 Express Edition)

ついでに
> System::Windows::Forms::MessageBox を使おうとすると、#define されてるせいで、
> System::Windows::Forms::MessageBoxA/W になっちゃってコケるかもしれません。
の確認もしたところコケずに上手くいっているポイです。


Blue  2006-01-20 09:52:46  No: 60393

ちなみに
Win32 コンソール アプリケーション
でプロジェクトをつくると
> プロジェクトの プロパティ ページ の リンカ の 入力 の 追加の依存ファイルに指定
は自動的に、「親またはプロジェクト規定値からの継承」になるようです。
# CLRプログラムの場合は、デフォルトが$(NOINHERIT)でした。

ついでに
> 実はあらかじめ
> #undef UNICODE
> と、していたり・・・
も、プロパティの全般-文字セット で設定するほうがよさそう。

>   ・デフォルトでUNICODEビルドになっている。
Win32プロジェクトの方もたしかそうだったと。
だから、TCHARメッチャ意識したソースになっちゃっていますね。


DD.  2006-01-20 18:25:10  No: 60394

皆様ありがとうございます<(_ _)>

無事解決致しました。

Blueさんの
>> プロジェクトの プロパティ ページ の リンカ の 入力 の 追加の依存ファイルに指定
>は自動的に、「親またはプロジェクト規定値からの継承」になるようです。
># CLRプログラムの場合は、デフォルトが$(NOINHERIT)でした。
から「プロジェクトのプロパティ」の「リンカ」→「入力」部で
「継承の値」には指定 lib がリンクしてあったのですが、
その下の「親またはプロジェクトの既定値から継承」のチェックがはずれていたために、継承がなされていなかったのだと思われます。

チェックを付けたところ、無事リンクされエラーは消失致しました。

普通の Win32 アプリなら問題なかったのに(´・ω・`)
Blueさんならびに助言頂いた皆様に感謝致します。<(_ _)>

#これでやっと今朝 the spoke の登録完了が終了したから VS2005 Pro が入れられる(´Д`*)


Blue  2006-01-20 18:54:06  No: 60395

つ[□←解決時は質問者本人がここをチェックしてください]

ついでに、もう時間ないですが
> #これでやっと今朝 the spoke の登録完了が終了したから VS2005 Pro が入れられる(´Д`*)

http://www.belution.com/lounge/ja/viewtopics.php?id=20030630090049&disp=27
に報告したほうがよいかと。


DD.  2006-01-20 18:56:11  No: 60396

解決チェックを忘れていました。
申し訳ないです。

>http://www.belution.com/lounge/ja/viewtopics.php?id=20030630090049&disp=27
>に報告したほうがよいかと。
ですね^^
詳細載せておきます。


sgm  2007-01-26 01:35:25  No: 60397

ネットサーフィンでたまたま覗いてたら…。
自分も…

------ ビルド開始: プロジェクト: MakeData, 構成: Debug Win32 ------
リンクしています...
MakeData.obj : error LNK2028: 未解決のトークン (0A000011) "extern "C" int __stdcall GetOpenFileNameW(struct tagOFNW *)" (?GetOpenFileNameW@@$$J14YGHPAUtagOFNW@@@Z) が関数 "private: void __clrcall MakeData::Form1::LoadTextData(struct HWND__ *,unsigned char *,int)" (?LoadTextData@Form1@MakeData@@$$FA$AAMXPAUHWND__@@PAEH@Z) で参照されました。
MakeData.obj : error LNK2019: 未解決の外部シンボル "extern "C" int __stdcall GetOpenFileNameW(struct tagOFNW *)" (?GetOpenFileNameW@@$$J14YGHPAUtagOFNW@@@Z) が関数 "private: void __clrcall MakeData::Form1::LoadTextData(struct HWND__ *,unsigned char *,int)" (?LoadTextData@Form1@MakeData@@$$FA$AAMXPAUHWND__@@PAEH@Z) で参照されました。
C:\Documents and Settings\matushita\デスクトップ\C言語\MakeData\Debug\MakeData.exe : fatal error LNK1120: 外部参照 2 が未解決です。
ビルドログは "file://c:\Documents and Settings\デスクトップ\C言語\MakeData\MakeData\Debug\BuildLog.htm" に保存されました。
MakeData - エラー 3、警告 0
========== ビルド: 0 正常終了、1 失敗、0 更新、0 スキップ ==========

こんな感じでエラーが出てましたがDD.さんと同じようにチェックがはずれてました…orz
チェックを付けたらエラーが消えました。
色んなサイトで調べていたのでとても助かりました。
ありがとうございますm(_ _)m


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加