|
-
February 5th, 2012, 09:40 PM
#1
Make HWND global LNK2005
hey folks,
im codin a win32 app. and i want to make the HWND hWnd to a global variable. well i put all this gui stuff in a file GUI.h and GUI.cpp. now i want to make the window handle global so i can acces it if i include the header. Now my GUI.h looks like that:
but if i do i get the error :
Fehler 5 error LNK2005: "struct HWND__ * MyWindowHandle" (?MyWindowHandle@@3PAUHWND__@@A) ist bereits in GUI.obj definiert.
[already defined in GUI.obj]
What am i doing wrong?
GUI.h
Code:
#include "Windows.h"
#ifndef _GUI
#define _GUI
HWND WindowHandle;
int initGUI(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpcmdline, int ncmdshow);
#endif //_GUI
#endif //_GUI
Main.cpp
Code:
#include "Windows.h"
#include "GUI.h"
//==============================================================================
int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpcmdline, int ncmdshow)
//==============================================================================
{
return initGUI(hInst, hPrevInst, lpcmdline, ncmdshow);
} // WinMain
GUI.cpp
Code:
#include "GUI.h"
#include "Commctrl.h"
#include "Tchar.h"
#include "time.h"
#include <vector>
using std::vector;
#include "TableManager.h"
#include "resource.h"
#pragma comment(lib, "comctl32.lib")
//_____________________________________________________________________________
// DEFINES
#define TMR_0_ID 01
#define LBX_0_ID 10
#define BTN_0_ID 20
#define BTN_1_ID 21
#define DTP_0_ID 30
#define DTP_1_ID 31
#define STB_0_ID 40
//_____________________________________________________________________________
// Variables
static wchar_t AppTitle[] = L"THB"; // The string that appears in the application's title bar.
static tm sysTime;
static HWND hLBX;
static HWND hBTN[2];
static HWND hDTP[2];
static HWND hSTB;
static HFONT font;
static TABLEMANAGER TableManager;
static bool AutoplayerStatus = 0;
//_____________________________________________________________________________
// Prototypes
LRESULT CALLBACK WindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
void Heartbeat(HWND hWnd);
void GUI_onCreate(HWND hWnd);
void GUI_onClose(HWND hWnd);
void GUI_Update(HWND hWnd);
void GUI_StopAP(HWND hWnd);
void GUI_StartAP(HWND hWnd);
void InstanciateAllSingletons();
//==============================================================================
int initGUI(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpcmdline, int ncmdshow)
{
MSG message;
HWND hWnd;
WNDCLASSEX windowclass;
INITCOMMONCONTROLSEX icex;
// Struktur für Fenstereigenschaften
windowclass.cbSize = sizeof (WNDCLASSEX);
windowclass.style = CS_HREDRAW | CS_VREDRAW;
windowclass.lpfnWndProc = WindowProc;
windowclass.cbClsExtra = 0;
windowclass.cbWndExtra = 0;
windowclass.hInstance = hInst;
windowclass.hIcon = LoadIcon (hInst, MAKEINTRESOURCE(IDI_ICON1));
windowclass.hIconSm = LoadIcon (hInst, MAKEINTRESOURCE(IDI_ICON1));
windowclass.hCursor = LoadCursor (NULL, IDC_ARROW);
windowclass.hbrBackground = (HBRUSH)COLOR_BACKGROUND+1;
windowclass.lpszMenuName = NULL; //(LPCWSTR)("Datei");
windowclass.lpszClassName = AppTitle;
// Fensterklasse registrieren
if (!RegisterClassEx (&windowclass) ){
MessageBox(NULL, _T("Call to RegisterClassEx failed!"), AppTitle, NULL);
return 1;
}
icex.dwSize = sizeof(icex);
icex.dwICC = ICC_DATE_CLASSES;
InitCommonControlsEx(&icex);
// Fenster-Handle erzeugen
hWnd = CreateWindowEx (
NULL,//WS_EX_TOOLWINDOW,
AppTitle,
AppTitle,
WS_VISIBLE | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT,
406, 328,
NULL,
NULL,
hInst,
NULL);
// Test Create();
if (!hWnd){
MessageBox(NULL,_T("Call to CreateWindow failed!"), AppTitle, NULL);
return 1;
}
ShowWindow(hWnd, SW_SHOWNORMAL);
UpdateWindow(hWnd);
// Empfange Nachrichten
while (GetMessage(&message, NULL, 0, 0) ){
TranslateMessage (&message);
DispatchMessage (&message);
}
return (int)(message.wParam);
} // WinMain
//==============================================================================
void GUI_onCreate(HWND hWnd){
// Create Forms
HINSTANCE hInst = GetModuleHandle(NULL);
hLBX = CreateWindow(L"LISTBOX",L"TableListView",WS_VISIBLE|WS_CHILD|LBS_NOINTEGRALHEIGHT|LBS_NOTIFY|WS_VSCROLL|WS_BORDER|LBS_NOSEL,0, 0, 200, 200,hWnd, (HMENU)LBX_0_ID, hInst, NULL);
hBTN[0] = CreateWindow(L"BUTTON",L"AP", WS_CHILD|WS_VISIBLE | BS_CHECKBOX | BS_PUSHLIKE, 200, 0, 40, 40, hWnd, (HMENU)BTN_0_ID, hInst, NULL);
hBTN[1] = CreateWindow(L"BUTTON",L"Pref", BS_PUSHBUTTON|WS_CHILD|WS_VISIBLE, 200, 40, 40, 40, hWnd, (HMENU)BTN_1_ID, hInst, NULL);
hDTP[0] = CreateWindow(DATETIMEPICK_CLASS,TEXT("StartTime"),WS_BORDER|WS_CHILD|WS_VISIBLE|DTS_TIMEFORMAT, 200, 80, 70, 25, hWnd, (HMENU)DTP_0_ID, hInst, NULL);
hDTP[1] = CreateWindow(DATETIMEPICK_CLASS,TEXT("StopTime"), WS_BORDER|WS_CHILD|WS_VISIBLE|DTS_TIMEFORMAT, 270, 80, 70, 25, hWnd, (HMENU)DTP_1_ID, hInst, NULL);
hSTB = CreateWindow(STATUSCLASSNAME, NULL, WS_CHILD| WS_VISIBLE, 0,0,0,0, hWnd, (HMENU)STB_0_ID, hInst, NULL);
// Change preferences
DateTime_SetFormat(hDTP[0],L"HH':'mm");
DateTime_SetFormat(hDTP[1],L"HH':'mm");
// Tell the status bar to create the window parts.
int edges[4] = {40,80,350,-1};
SendMessage(hSTB, SB_SETPARTS, (WPARAM) 4, (LPARAM)edges);
InstanciateAllSingletons();
// Load the Tablemap
p_Tablemap->LoadTablemap(BWIN_TABLEMAP_FILENAME);
GUI_Update(hWnd);
// Create timer for tablemanager
if(!SetTimer(hWnd, TMR_0_ID, 1000, NULL))
MessageBox(NULL, _T("No timer available"), AppTitle, MB_ICONINFORMATION);
}
//==============================================================================
void GUI_onClose(HWND hWnd){
//==============================================================================
if(AutoplayerStatus && !TableManager.countOpenTables())
MessageBox(NULL, _T("AP is still seated."), AppTitle, NULL);
else{
KillTimer(hWnd, TMR_0_ID);
PostQuitMessage (0);
}
}
//==============================================================================
void GUI_Update(HWND hWnd){
//==============================================================================
// Update Time
time_t rawtime = time(NULL);
localtime_s(&sysTime, &rawtime );
// Update listbox
TableManager.UpdateListBox(hLBX);
//Update statusbar
const int l = 15;
wchar_t s[l];
memset(s,0,sizeof(wchar_t)*l);
swprintf(s,L"NL %d",LIMIT);
SendMessage(hSTB, SB_SETTEXT, (SBT_NOBORDERS<<8)|0, (LPARAM)s);
memset(s,0,sizeof(wchar_t)*l);
swprintf(s,L"%0d/%0d", TableManager.countOpenTables(), MAXTABLES);
SendMessage(hSTB, SB_SETTEXT, (SBT_NOBORDERS<<8)|1, (LPARAM)s);
memset(s,0,sizeof(wchar_t)*l);
swprintf(s,L"AP: %s", AutoplayerStatus ? L"AN" : L"AUS");
SendMessage(hSTB, SB_SETTEXT, (SBT_NOBORDERS<<8)|2, (LPARAM)s);
memset(s,0,sizeof(wchar_t)*l);
swprintf(s,L"%0d:%0d", sysTime.tm_hour, sysTime.tm_min);
SendMessage(hSTB, SB_SETTEXT, (SBT_NOBORDERS<<8)|3, (LPARAM)s);
}
//==============================================================================
void GUI_StartAP(HWND hWnd){
//==============================================================================
AutoplayerStatus = 1;
SendMessage(hBTN[0], BM_SETCHECK, BST_CHECKED, NULL);
}
//==============================================================================
void GUI_StopAP(HWND hWnd){
//==============================================================================
AutoplayerStatus = 0;
SendMessage(hBTN[0], BM_SETCHECK, BST_UNCHECKED, NULL);
}
//==============================================================================
void Heartbeat(HWND hWnd){
TableManager.Update();
GUI_Update(hWnd);
}
//==============================================================================
void InstanciateAllSingletons(){
if (!p_Tablemap) p_Tablemap = new TABLEMAP;
// if (!p_Scraper) p_Scraper = new SCRAPER;
}
//==============================================================================
LRESULT CALLBACK WindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
//==============================================================================
{
switch (message){
//-------------------------------------------------------------------------
case WM_CREATE:{
GUI_onCreate(hWnd);
return (0);
}
//-------------------------------------------------------------------------
case WM_CLOSE:{
GUI_onClose(hWnd);
return (0);
}
//-------------------------------------------------------------------------
case WM_TIMER:{
switch (wParam){
case TMR_0_ID:
Heartbeat(hWnd);
return 0;
default:return 0;
}
}
//-------------------------------------------------------------------------
case WM_COMMAND:{
switch (LOWORD(wParam)){
case BTN_0_ID:
if(AutoplayerStatus)
GUI_StopAP(hWnd);
else
GUI_StartAP(hWnd);
return (0);
case BTN_1_ID:
return (0);
default:return 0;
}
}
//-------------------------------------------------------------------------
case WM_KEYDOWN:{
switch (wParam){
case VK_ESCAPE:
PostQuitMessage (0);
return (0);
case 0x31:
return (0);
case 0x32:
return (0);
case VK_LEFT:
return (0);
default:return 0;
}
//-------------------------------------------------------------------------
}
}
return (DefWindowProc (hWnd, message, wParam, lParam) );
} // WindowProc
-
February 5th, 2012, 10:33 PM
#2
Re: Make HWND global LNK2005
 Originally Posted by ImNotaBot
hey folks,
im codin a win32 app. and i want to make the HWND hWnd to a global variable. well i put all this gui stuff in a file GUI.h and GUI.cpp. now i want to make the window handle global so i can acces it if i include the header. Now my GUI.h looks like that:
When you use an include file, all you're doing is taking the text from the include file and placing it into your source file. Nothing more than that. So what does GUI.CPP and Main.cpp end up with?
You now have a declaration of MyWindowHandle in two modules. Now when the linker looks at both a.obj and b.obj, it sees two declarations of MyWindowHandle. The linker then gives the error that you have multiple definitions of MyWindowHandle.
One solution is to use the extern keyword for the globals in one module, and not use extern in the other module -- this has been discussed here many times (so a search will bring up those threads). Also any good C++ book explains the usage of extern for global variables.
But that is an inferior solution -- the real "solution" is to not use global variables and design your code differently so that there is no need for globals.
Regards,
Paul McKenzie
-
February 6th, 2012, 02:23 AM
#3
Re: Make HWND global LNK2005
To complete a little what Paul already stated:
Generally, in a Win32 application it's not necessary to store window handles.
That's because the window procedures get the window handle as parameter, then you can further pass it to handler functions.
Also, the notification messages come with the child window handles.
Also, there are WinAPI functions which can easily get a window handle (e.g. GetDlgItem).
And so on...
[ Moved thread ]
-
February 6th, 2012, 06:07 AM
#4
Re: Make HWND global LNK2005
Okay, but in fact I cant see *where* i declared MyWindowhandle two times, thats what surprised me. Do you see it? I just declared it in the GUI.h Nowhere else. I think my linker is kidding me
-
February 6th, 2012, 08:04 AM
#5
Re: Make HWND global LNK2005
 Originally Posted by ImNotaBot
Okay, but in fact I cant see *where* i declared MyWindowhandle two times, thats what surprised me. Do you see it?
I see it clearly.
I just declared it in the GUI.h Nowhere else. I think my linker is kidding me
Did you read my explanation? I'll quote again:
When you use an include file, all you're doing is taking the text from the include file and placing it into your source file.
You did this:
In both your source files. So what does GUI.h contain?
Regards,
Paul McKenzie
-
February 6th, 2012, 01:13 PM
#6
Re: Make HWND global LNK2005
I just declared it in the GUI.h Nowhere else.
You have to learn what #include actually does.
Best regards,
Igor
-
February 7th, 2012, 04:30 AM
#7
Re: Make HWND global LNK2005
 Originally Posted by ImNotaBot
I think my linker is kidding me 
A linker is never kidding. It just reports the mistakes you made.
-
February 9th, 2012, 05:27 AM
#8
Re: Make HWND global LNK2005
Okay now i understood what u want to tell me. But is this
Code:
#ifndef somethingThatShouldNotBeDuplicated
#define somethingThatShouldNotBeDuplicated
#endif
not exactly to avoid the duplictated inclusion?
greets and thanks for help.
-
February 9th, 2012, 06:01 AM
#9
Re: Make HWND global LNK2005
 Originally Posted by ImNotaBot
Okay now i understood what u want to tell me. But is this
Code:
#ifndef somethingThatShouldNotBeDuplicated
#define somethingThatShouldNotBeDuplicated
#endif
not exactly to avoid the duplictated inclusion?
Indeed it is "to avoid the duplictated inclusion" in the SAME module. But it cannot avoid the inclusion in another module!
Victor Nijegorodov
-
February 10th, 2012, 01:30 AM
#10
Re: Make HWND global LNK2005
 Originally Posted by ImNotaBot
Okay now i understood what u want to tell me. But is this
Code:
#ifndef somethingThatShouldNotBeDuplicated
#define somethingThatShouldNotBeDuplicated
#endif
not exactly to avoid the duplictated inclusion?
I'll quote once again:
When you use an include file, all you're doing is taking the text from the include file and placing it into your source file.
You're still not taking that quote and understanding it clearly.
You have two different modules, A.CPP and B.CPP. Each one of those files has #included that GUI.H header. So again, take the text in that header and copy/paste it in each one of those modules. That is what you end up with, and that is what the compiler is compiling.
Now ask yourself, how is A.CPP and B.CPP supposed to know that each other has seen your definition? What is this magic communication that each has? There isn't any. All the compiler sees is what it sees.
Now you have two object files created from compiling, A.OBJ and B.OBJ, so they still have that declaration in each one, and the linker sees both definitions.
Regards,
Paul McKenzie
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|