2016-04-07 10 views
0

私は小さなダイアログベースのWin32アプリケーションを作成しています。私は、メニューボタンをクリックすると、2番目のダイアログを作成して表示する必要があります。私はHWNDを外部ヘッダファイルで宣言されてい - wedge.h外部で宣言された変数の定義は、ある関数では機能しますが、別の関数では機能しません。

wedge.h

#pragma once 
#include <Windows.h> 
#include "utilities.h" 

extern HWND wedgedialog; 
INT_PTR CALLBACK WedgeProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); 

私は試してみて、私のWinMain関数でwedgedialogを定義して、私のDialogProc関数内で変数を使用し、Iリンカから「未解決の外部シンボル」エラーを受け取ります。 DialogProcでwedgedialogを定義して使用すると、すべて正常に動作します。定義が1つの機能では機能するが、他の機能では機能しないのはなぜですか?私のWinMainとDialogProc関数は同じファイルにあることを覚えておいてください。あなたは本当にグローバル変数を定義していない

main.cppに

INT_PTR CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); 
int WINAPI _tWinMain(HINSTANCE hInst, HINSTANCE h0, LPTSTR lpCmdLine, int nCmdShow) 
{ 
HWND hDlg; 
MSG msg; 
BOOL ret; 
InitCommonControls(); 
hDlg = CreateDialogParam(hInst, MAKEINTRESOURCE(MAIN), 0, DialogProc, 0); 


HWND wedgedialog = CreateDialog(GetModuleHandle(NULL), MAKEINTRESOURCE(WEDGE), hDlg, WedgeProc); 


ShowWindow(hDlg, nCmdShow); 
HMENU menu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU1)); 
SetMenu(hDlg, menu); 
while ((ret = GetMessage(&msg, 0, 0, 0)) != 0) { 
    if (ret == -1) 
     return -1; 
    if (!IsDialogMessage(hDlg, &msg)) { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 

} 
return 0; 
} 

INT_PTR CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 
{ 
switch (uMsg) 
{ 

case WM_CLOSE: 
    DestroyWindow(hDlg); 
    return TRUE; 
    break; 
case WM_DESTROY: 
    PostQuitMessage(0); 
    return TRUE; 
    break; 
case WM_COMMAND: 
    switch (LOWORD(wParam)) 
    { 
    case ID_EDIT_WEDGESETTINGS: 

     ShowWindow(wedgedialog, SW_SHOW); 
     break; 
    } 
    return TRUE; 
    break; 
} 
return FALSE; 
} 

答えて

1

。 _tWinMain関数のHWND型のwedgedialogという名前のローカル変数を宣言しています。あなたがextern宣言を持っているという理由だけで、そのローカル変数は自動的にグローバルに昇格しません。 extern宣言はどこかにグローバル変数があることをコンパイラに伝えます。そのため、DialogProcのコードはコンパイルされますが、実際にリンクするグローバルはありません。

この作品を作るために、あなたがそうのように、任意の関数の外で、実際にグローバル変数を宣言する必要があります:

HWND wedgedialog = NULL; 

次にメイン関数で、との行の先頭にHWND指定子を削除しますCreateDialog呼び出しは、単にローカルに宣言するのではなく、グローバルに割り当てるだけです。

必要に応じてヘッダにextern宣言を残しておくことができますが、他の機能でそのグローバルを使用している場合を除き、本当に必要はありません。間違いなくグローバルなデザインを使用するよりも優れたデザインがあります。静的メンバーを持つクラスを宣言して、少なくともグローバルな名前空間を避けることができます。あるいは、シングルトンオブジェクトを返す静的関数を持つクラスを持つこともできます。

0

"extern HWND wedgedialog;"実際に変数を割り当てるわけではありません。変数が別のファイルに割り当てられ、リンク中に解決されることをコンパイラに伝えるだけです。あなたの他のファイルの1つには、次のものが必要です:

"HWND wedgedialog;"

実際に変数をメモリに割り当てる。