プロが教える店舗&オフィスのセキュリティ対策術

こんにちは。私は30代の男性です。

「猫でもわかるプログラミング http://www.kumei.ne.jp/c_lang/index_sdk.html」の「Windows SDK編 第1部 」→「第28章 ボタンを使う 」をコピーして、VCで動作を確認しようとしたのですが、うまく動作しませんでした。

VCに関しては初心者なので、さっぱりわかりません。どのようにしたらボタンが表示されるようになるのでしょうか?解決策をお教え頂ければありがたいです。
宜しくお願いいたします。

A 回答 (8件)

★エラーメッセージを頼りに1つずつ修正して行きましょう。


・なお、警告メッセージはエラー扱いしないオプションを『プロパティ』で設定して下さい。
 これで一通り、コンパイルは通るようになります。→本当は警告メッセージもちゃんと修正
 すべきですがね。

・コンパイルを成功させたい場合は、回答番号 ANo.3 のサンプルをコピー&ペーストして下さい。
 インデント部が全角空白ですのでエディタなどの置換でタブ文字(スペース)に一括変換して下さい。
 そして、そのソースの InitApp() 関数の次の1行を編集して下さい。
 編集前⇒『wcex.lpfnWndProc = DefWindowProc;』
 編集後⇒『wcex.lpfnWndProc = WndProc;』
・次は『第28章 ボタンを使う』ページに書かれているウィンドウ・プロシージャ関数(WndProc)と
 その下に書かれているフォント設定関数(SetMyFont)をコピー&ペーストします。ペーストする位置と
 順番は回答番号 ANo.3 のサンプルの3つの関数を含み次の順に並べて下さい。
 (1)SetMyFont() ←挿入1(必ず WndProc() 関数よりも上に挿入)
 (2)WndProc() ←挿入2(必ず SetMyFont() 関数よりも下に挿入)
 (3)InitInstance()
 (4)InitApp()
 (5)WinMain()
 『static TCHAR szClassName[] = TEXT("クラス名");』と InitInstance() 関数の間に SetMyFont() と
 WndProc() の2つの関数を挿入して下さい。土台のソースは、回答番号 ANo.3 のサンプルを使って下さい。
 →ANo.3 のサンプルならば、エラーが出ないのでこれを使えば楽です。
・上記まで作成したら細かい場所を修正します。
 (1)SetMyFont() 関数の return 文の前に次の1行を挿入します。
  『UNREFERENCED_PARAMETER( hdc );』です。
  この意味は、変数 hdc が使われていないという警告メッセージを出さなくするための対策です。
  WinMain() 関数でも lpsCmdLine 変数が参照などされていないので UNREFERENCED_PARAMETER マクロを
  使っています。
 (2)ここからは WndProc() 関数の修正です。
  修正場所は『修正前』の行を上手く見つけて下さい。上から順番に記述しています。
  修正前⇒『hInst = (HINSTANCE)GetWindowLong( hWnd, GWL_HINSTANCE );』
  修正後⇒『hInst = (HINSTANCE)(__int64)GetWindowLong( hWnd, GWL_HINSTANCE );』
  ※『(__int64)』キャストを挿入します。
  
  修正前⇒『hFontOld = SelectObject( hdc, hFont );』
  修正後⇒『hFontOld = (HFONT)SelectObject( hdc, hFont );』
  ※『(HFONT)』キャストを挿入します。
  ※『WM_PAINT』メッセージの部分に2箇所あるので、その2箇所を編集します。
 (3)『第28章 ボタンを使う』ページにある『#define』部分の5行を『#include <windows.h>』の下に
  記述します。そして、さらにその下に『int nFont = 1;』と『int nCol = 1;』を追加して下さい。
・上記の場所を修正すればコンパイルできると思います。
 土台のソースは、あくまでも私が送った回答番号 ANo.3 のサンプルですよ。
 『第28章 ボタンを使う』ページの WinMain() 関数は GetMessage() 関数の戻り値を正しく見ていないため
 場合によってはプログラムが終了しなくなってしまいます。このことは MSDN のマニュアルや同サイトの
 http://www.kumei.ne.jp/c_lang/loop.htm→『メッセージ・ループ』という項目にも書かれています。注意!

最後に:
・GetWindowLong() 関数などの整数の戻り値にキャストをつける時に __int64 というキャストを追加して
 ください。これは、GetWindowLong() 関数の戻り値が 32 ビットに対して、キャストするハンドルが 64 ビット
 扱いの場合に必要なのです。__int64 のキャストで整数拡張して 64 ビットに合わせてからハンドルなどの
 HINSTANCE 型にキャストします。
・あと SelectObject() 関数の戻り値は、HGDIOBJ 型なので HFONT 型の変数に代入する場合は、HFONT にキャスト
 する必要があります。
・以上。おわり。
    • good
    • 0
この回答へのお礼

Oh-Orange様
再度ご回答いただきありがとうございました。大変勉強になりました。ありがとうございました。

お礼日時:2007/04/17 13:12

> 'font02.exe': 'C:\WINNT\system32\comctl32.dll' を読み込みました。

必要な DBG ファイルが見つからないか、開けません。
> 'font02.exe': 'C:\WINNT\system32\imejpknl.dll' を読み込みました。シンボルが読み込まれていません。

全部こんな感じのメッセージですか?
でしたら、「エラー」を報告するメッセージではありませんので
気にすることはありません。

デバッグ実行すると、Cのソース行の単位で
ブレークポイントを張ったり
ステップ実行することができますが、
作成した実行ファイルが使っているdllには
それらを可能にする情報がありません。
ということを知らせているだけです。

MSDNに契約すれば必要なシンボルファイルが
手に入ったような気もしますが
入門者レベルでそこまですることもないでしょう。
    • good
    • 0
この回答へのお礼

再度ご回答いただきありがとうございます。

>全部こんな感じのメッセージですか?
でしたら、「エラー」を報告するメッセージではありませんので
気にすることはありません。

全部こんな感じです。ありがとうございました。

お礼日時:2007/04/17 13:09

★『猫でもわかるプログラミング』サイトは警告メッセージがたくさん出ます。


・回答者 No.4 さんの補足にある内容から正しいキャストがされていなかったり、文字列を TEXT() マクロを
 使っていないためか、『LPCSTR』から『LPCWSTR』に変更できませんのエラーメッセージの嵐のはずです。

解決策1:
・文字列には TEXT() を使って記述しなおす。
 修正前⇒LPCSTR szClassName = "font02"; //クラス名
 修正後⇒LPCSTR szClassName = TEXT("font02"); //クラス名
 ※すべての文字列について TEXT() を使って記述します。
 ※このマクロを利用するとマルチバイト環境(シフトJIS)や Unicode 環境(ワイド文字)の両方の環境に
  コンパイル・オプションで切り替えられるようになります。コンパイラの VC 2005.NET は初期設定で
  Unicode になっているためマルチバイト環境用に記述されているソースはエラーの嵐になります。
 ※この文字列の一番簡単な解決策は、回答者 No.5 さんの回答にあるように『プロパティ』設定から
  『マルチバイト文字セットを使用する』を選択します。でも、今後のことも考えてこれから文字列を
  記述する場合は TEXT() マクロを利用して書く習慣をつけたほうが良いでしょう。
・正しいキャストを入れること。→回答者 No.5 さんの回答を参考に。

その他:
・これからは、文字列の型は『TCHAR』型の配列で指定して下さい。『char』型配列ではありません。
 『UCHAR』、『char』はマルチバイト文字を扱う『型』です。文字列定数では頭に『L』は付けない。→"あいうえお"
 『WCHAR』、『wchar_t』は Unicode 文字を扱う『型』です。文字列定数では頭に『L』を付けます。→L"あいうえお"
 上記の2つをコンパイル・オプションから切り替えるように記述したい場合は『TCHAR』の型で宣言、
 TEXT() マクロを使って定数を記述します。→TCHAR szBuff[256];、TEXT("あいうえお") などとする。
・また文字列のポインタは、TCHAR 型のポインタと記述する以外に次の型も存在します。
 『PSTR』、『LPSTR』は CHAR 型へのポインタを typedef で再定義されています。
 『PCSTR』、『LPCSTR』は const CHAR 型へのポインタを typedef で再定義されています。
 『LPTSTR』は TCHAR 型へのポインタを typedef で再定義されています。
 『LPCTSTR』は const TCHAR 型へのポインタを typedef で再定義されています。
 上記以外にも『PCHAR』、『PTCHAR』などあります。
・いっぱいありますが使うのは『TCHAR』、『LPTSTR』、『LPCTSTR』の3つだけで良いでしょう。
 (1)文字配列を宣言するときは『TCHAR』を使う。→TCHAR szBuff[256];
 (2)文字列ポインタを宣言するときは『LPTSTR』を使う。→LPTSTR lpDest;
 (3)const 型の文字列ポインタ宣言は『LPCTSTR』を使う。→LPCTSTR lpString;
http://wisdom.sakura.ne.jp/system/winapi/win32/w …→『Windowsと文字コード』
http://hpcgi1.nifty.com/MADIA/Vcbbs/wwwlng.cgi?p …→『UCHAR→TCHAR変換』

最後に:
・下の『参考URL』に『Visual C++ 2005 C/C++ランタイム ライブラリ新機能概要』という項目があります。
 また、『猫でもわかるプログラミング』サイトでも次の項目があります。
 http://www.kumei.ne.jp/c_lang/net2005/index.html→『VS2005でうまくビルドできない時は』
 http://www.kumei.ne.jp/c_lang/net2005/sample.htm→『VS2005サンプルプログラム』
 ※ここの2つのページに、今回の質問の回答となる内容があります。→読んでないでしょう!
 ※両方ともトップページのカウンタのすぐ下の部分にあるリンク項目です。ここ読みましょう。
・あと pragma 指定を1行追記しても上手くいくらしいです。→私は試していないが…。
 『#pragma warning(disable : 4996)』の1行をソースの一番上に記述するだけで古い形式の関数の使用警告を
 無効にすることが出来るようです。もし、TEXT() マクロ使用以外でエラーが出た場合は pragma 指定を行って
 下さい。上手くいくはずです。下の『参考URL』にも書かれてあるので。
・以上。今後のこのサイトの参考にして下さい。

参考URL:http://www.microsoft.com/japan/msdn/security/dem …
    • good
    • 0
この回答へのお礼

いろいろとアドバイスをありがとうございます。

No.5さんのところで補足しましたが、表示はされるのですがエラーが少し出て、どうしたらエラーが表示されなくなるのか(もしくはエラーが出ていてもいいのか)考えているところです。

他にVCでやりたいことがありますので、そちらについては別に投稿させて頂きます。

お礼日時:2007/04/17 08:44

> c:\documents and settings\my documents\visual studio 2005\projects\font02\font02\font02.cpp(40)



ディレクトリの名前から判断するとやはり 2005ですか。
もしプロジェクトを作成して試しているのなら、そのプロジェクトを開いて

> VC2005では、デフォルトでUNICODEになっています。 古いOSで動かしたいなら、UNICODEは止めたほうがいいです。
> プロジェクトのプロパティを開き、[構成プロパティ]-[全般]-[文字セット]を 「マルチバイト文字セットを使用する」に変更することお奨めします。

この変更を行ってください。
その上で、

55行目を
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
のように、
145行目と149行目を
hFontOld = (HFONT)SelectObject(hdc, hFont);
のように変更してください。
多少行番号がずれているかもしれませんが、行の内容から判断してください。

こちらで試したのと微妙にエラーの内容が違うので、上記の修正をした後でも
まだエラーが残るかもしれませんが、そのときは再度補足してください。
エラーメッセージを貼り付けるのをお忘れなく。

Re: WinAPIメッセージボックスについて - MSDN フォーラム
http://forums.microsoft.com/MSDN-JA/ShowPost.asp …

VC2005でエラーになる理由ですが、まあコンパイラの仕様が変わったということですね。
より厳しくエラーを招きがちな記述をチェックするようになったということです。
猫でも…のサンプルは VC 4.2でチェックしたとあるのでだいぶ古いですね。
アップデートしないんでしょうか。

この回答への補足

下記のように修正したのですが、よろしいでしょうか(とりあえず動けばいいと思ったので)?その下にはエラーメッセージ(?)が出ました(字数の関係でいくつかは削除しました)。エラーが表示されないようにするためにはどうしたらよろしいでしょうか?

//ウィンドウプロシージャ

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
int id;
HDC hdc;
HFONT hFont, hFontOld;
PAINTSTRUCT ps;
HWND hButtonWnd1, hButtonWnd2, hButtonWnd3, hButtonWnd4,
hButtonWnd5, hButtonWnd6;
HINSTANCE hInst;
hInst = (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE);
switch (msg) {
case WM_CREATE:
hButtonWnd1 = CreateWindow(
"BUTTON", "Button1",
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
20, 20, 100, 30, hWnd, (HMENU)ID_MI, hInst ,NULL);
hButtonWnd2 = CreateWindow(
"BUTTON", "Button2",
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
130, 20, 100, 30, hWnd, (HMENU)ID_GO, hInst, NULL);
hButtonWnd3 = CreateWindow(
"BUTTON", "終了",
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
240, 20, 100, 30, hWnd, (HMENU)ID_END, hInst, NULL);
break;
case WM_COMMAND:
switch(LOWORD(wp)) {
case ID_MI:
nFont = 1;
InvalidateRect(hWnd, NULL, TRUE);
break;
case ID_GO:
nFont = 2;
InvalidateRect(hWnd, NULL, TRUE);
break;
case ID_RED:
nCol = 1;
InvalidateRect(hWnd, NULL, TRUE);
break;
case ID_BLUE:
nCol = 2;
InvalidateRect(hWnd, NULL, TRUE);
break;
case ID_END:
SendMessage(hWnd, WM_CLOSE, 0, 0L);
break;
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
switch (nFont) {
case 1:
hFont = SetMyFont(hdc, (LPCTSTR)"MS 明朝");
hFontOld = (HFONT)SelectObject(hdc, hFont);
break;
case 2:
hFont = SetMyFont(hdc, (LPCTSTR)"MS ゴシック");
hFontOld = (HFONT)SelectObject(hdc, hFont);
break;
}
switch (nCol) {
case 1:
SetTextColor(hdc, RGB(255, 0, 0));
break;
case 2:
SetTextColor(hdc, RGB(0, 0, 255));
break;
}
TextOut(hdc, 10, 120, (LPCTSTR)"猫でもわかるフォント", 20);
SelectObject(hdc, hFontOld);
DeleteObject(hFont);
EndPaint(hWnd, &ps);
break;
case WM_CLOSE:
id = MessageBox(hWnd,
(LPCSTR)"終了してもよいですか",
(LPCSTR)"終了確認",
MB_YESNO | MB_ICONQUESTION);
if (id == IDYES) {
DestroyWindow(hWnd);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, msg, wp, lp));
}
return 0L;
}

'font02.exe': 'C:\WINNT\system32\comctl32.dll' を読み込みました。必要な DBG ファイルが見つからないか、開けません。
'font02.exe': 'C:\WINNT\system32\imejpknl.dll' を読み込みました。シンボルが読み込まれていません。
プログラム '[1664] font02.exe: ネイティブ' はコード 0 (0x0) で終了しました。

補足日時:2007/04/17 08:33
    • good
    • 0

> エラーがたくさん出て、


> (1)コンパイルできなかった。
> です。

どんなエラーだったのかくらい書いてください。
貼り付けられないほどたくさんならば、頭のいくつかだけでも良いです。
いずれにしろ、補足になってないですよ。


あと、VCをお使いとのことですが、バージョンは
どれですか?

この辺かもと思いつつ。

Re: Win32 アプリケーションの作成、Expressにて - MSDN フォーラム
http://forums.microsoft.com/MSDN-JA/ShowPost.asp …

この回答への補足

ご回答ありがとうございます。エラーメッセージは下記のようなものが出ます。

------ ビルド開始: プロジェクト: font02, 構成: Debug Win32 ------
コンパイルしています...
font02.cpp
c:\documents and settings\my documents\visual studio 2005\projects\font02\font02\font02.cpp(40) : warning C4244: 'return' : 'WPARAM' から 'int' への変換です。データが失われる可能性があります。
c:\documents and settings\my documents\visual studio 2005\projects\font02\font02\font02.cpp(55) : error C2440: '=' : 'HGDIOBJ' から 'HBRUSH' に変換できません。
'void*' から非 'void' 型への変換には明示的なキャストが必要です。
c:\documents and settings\my documents\visual studio 2005\projects\font02\font02\font02.cpp(57) : error C2440: '=' : 'LPCSTR' から 'LPCWSTR' に変換できません。
指示された型は関連がありません。変換には reinterpret_cast、C スタイル キャストまたは関数スタイルのキャストが必要です。
c:\documents and settings\my documents\visual studio 2005\projects\font02\font02\font02.cpp(77) : error C2664: 'CreateWindowExW' : 2 番目の引数を 'LPCSTR' から 'LPCWSTR' に変換できません。(新しい機能 ; ヘルプを参照)
指示された型は関連がありません。変換には reinterpret_cast、C スタイル キャストまたは関数スタイルのキャストが必要です。
c:\documents and settings\my documents\visual studio 2005\projects\font02\font02\font02.cpp(96) : warning C4312: '型キャスト' : 'LONG' からより大きいサイズの 'HINSTANCE' へ変換します。
c:\documents and settings\my documents\visual studio 2005\projects\font02\font02\font02.cpp(102) : error C2664: 'CreateWindowExW' : 2 番目の引数を 'const char [7]' から 'LPCWSTR' に変換できません。(新しい機能 ; ヘルプを参照)
指示された型は関連がありません。変換には reinterpret_cast、c:\documents and settings\my documents\visual studio 2005\projects\font02\font02\font02.cpp(152) : error C2440: '=' : 'HGDIOBJ' から 'HFONT' に変換できません。
'void*' から非 'void' 型への変換には明示的なキャストが必要です。
c:\documents and settings\my documents\visual studio 2005\projects\font02\font02\font02.cpp(172) : error C2664: 'MessageBoxW' : 2 番目の引数を 'LPCSTR' から 'LPCWSTR' に変換できません。(新しい機能 ; ヘルプを参照)
指示された型は関連がありません。変換には reinterpret_cast、C スタイル キャストまたは関数スタイルのキャストが必要です。
ビルドログは "file://c:\Documents and Settings\My Documents\Visual Studio 2005\Projects\font02\font02\Debug\BuildLog.htm" に保存されました。
font02 - エラー 11、警告 2
========== ビルド: 0 正常終了、1 失敗、0 更新、0 スキップ ==========

補足日時:2007/04/16 20:54
    • good
    • 0

★『Windows アプリケーション』で作っていますか?


・もしも、コンソール・アプリケーションならばコンパイルできません。
 GUI のアプリケーションを作成するようにオプションを切り替えて下さい。
・ちなみに VC のバージョンはどれですか?
 (1)VC 6.0
 (2)VC 2003.NET
 (3)VC 2005.NET
 (4)上記以外
 下の『参考URL』をどうぞ。→読みましたか?
・次のサンプルをどうぞ。

#include <windows.h>

// ウィンドウクラス名
static TCHAR szClassName[] = TEXT("クラス名");

// ウィンドウの生成
BOOL InitInstance( HINSTANCE hInst, int nCmdShow )
{
 HWND hWnd;
 
 hWnd = CreateWindow( szClassName,
  TEXT("タイトル文字列"),
  WS_OVERLAPPEDWINDOW,
  CW_USEDEFAULT,
  CW_USEDEFAULT,
  CW_USEDEFAULT,
  CW_USEDEFAULT,
  NULL,
  NULL,
  hInst,
  NULL );
 
 if ( hWnd != NULL ){
  ShowWindow( hWnd, nCmdShow );
  UpdateWindow( hWnd );
  return( TRUE );
 }
 return( FALSE );
}

// ウィンドウ・クラスの登録
BOOL InitApp( HINSTANCE hInst )
{
 WNDCLASSEX wcex;
 
 wcex.cbSize = sizeof( WNDCLASSEX );
 wcex.style = (CS_HREDRAW | CS_VREDRAW);
 wcex.lpfnWndProc = DefWindowProc;
 wcex.cbClsExtra = 0;
 wcex.cbWndExtra = 0;
 wcex.hInstance = hInst;
 wcex.hIcon = LoadIcon( NULL, MAKEINTRESOURCE(IDI_APPLICATION) );
 wcex.hIconSm = LoadIcon( NULL, MAKEINTRESOURCE(IDI_APPLICATION) );
 wcex.hCursor = LoadCursor( NULL, MAKEINTRESOURCE(IDC_ARROW) );
 wcex.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
 wcex.lpszMenuName = NULL;
 wcex.lpszClassName = szClassName;
 return( RegisterClassEx(&wcex) );
}

// メイン関数
int WINAPI WinMain( HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow )
{
 BOOL bRet;
 MSG Msg;
 
 if ( hPrevInst == NULL ){
  if ( !InitApp(hCurInst) ){
   return( 0 );
  }
 }
 if ( !InitInstance(hCurInst,nCmdShow) ){
  return( 0 );
 }
 while ( (bRet = GetMessage(&Msg,NULL,0,0)) != 0 ){
  if ( bRet < 0 ){
   break;
  }
  TranslateMessage( &Msg );
  DispatchMessage( &Msg );
 }
 UNREFERENCED_PARAMETER( lpsCmdLine );
 return( (int)Msg.wParam );
}

最後に:
・今までは『コンソール・アプリケーション』でしたが、今回のプログラムは
 『Windows アプリケーション』という Win32 プロジェクトを選択しないと出来ません。
 オプションなどを確認して下さい。
・上のソースをコピー&ペーストして試してみて下さい。ただし、インデント部が全角ですので
 タブ文字に一括変換して下さい。→コンパイルする前に『Win32 プロジェクト』に変更して下さい。
・成功すると真っ白なウインドウが作成されます。
・以上。結果報告を待っています。

参考URL:http://www.kumei.ne.jp/c_lang/net/index.html
    • good
    • 0
この回答へのお礼

Oh-Orange様
わざわざソースコードありがとうございます。

>・ちなみに VC のバージョンはどれですか?

(3)VC 2005.NET
です。

Oh-Orange様のコードはこれから試してみます。先程は「font02」という名前のファイルを作って、そこの「font02.cpp」に、「第28章 ボタンを使う」のコードをコピペしました。貼り付けるところが悪かったのでしょうか?

お礼日時:2007/04/16 20:47

そこに載っているコードをそのままコピー&ペーストして、


Borland C++ Compiler 5.5でコンパイルしたところ、
exeファイルを正しく作成し、実行結果も正常でした。
ウィンドウ上のフォントや色の切替を正しく行なえました。
よって、サイト上の情報は正しいと判断できます。
以上、参考情報でした。
    • good
    • 0
この回答へのお礼

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

>Borland C++ Compiler 5.5でコンパイルしたところ、
exeファイルを正しく作成し、実行結果も正常でした。

ホントですか。自分はいまだコンパイルできませんよ。なんででしょう?

お礼日時:2007/04/16 20:41

★最初に『猫でもわかるプログラミング』サイトは Windows 環境ですよ。


・『うまく動作しませんでした』とはどのように上手く動作しなかったのですか?
 (1)コンパイルできなかった。
 (2)コンパイル出来たが実行はできなかった。→無反応やエラー表示などあったのか?
 (3)実行は出来たがボタンが表示されなかった。
 (4)その他
 どれですか?
・以上。補足要求します。

この回答への補足

Oh-Orange様
いつも御回答頂きありがとうございます。

エラーがたくさん出て、
(1)コンパイルできなかった。
です。

補足日時:2007/04/16 16:20
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!