Hi,
It has been a long time since I have done C, so please forgive my simple question. I am getting the following linker error in VC++6:
Compiling...
window.cpp
main.cpp
Linking...
window.obj : error LNK2005: "struct HWND__ * windowHandle" (?windowHandle@@3PAUHWND__@@A) already defined in main.obj
The way my code is structured is that I have a main.cpp that contains my WinMain function, and I have a window.h file that contains my "window" function prototypes and my global declaration of HWND windowHandle (which is giving me the problem). window.h is included in both window.cpp and main.cpp. I assume this is giving me the problem. Can some kind soul explain how I can set up my files to that I do not get this problem? I want to keep HWND windowHandle global so it is visible to both window.cpp and main.cpp. Thanks so much for any help. I''ll include my code below in case it helps...
window.h
// include files
#ifndef FLAG
#define FLAG
#include
#include
#define WIN32_LEAN_AND_MEAN
// globals
HWND windowHandle;
// prototypes
bool createWindow(HINSTANCE hInstance);
void showWindow(int iShowCmd);
LRESULT CALLBACK messageHandler(HWND wHandle, UINT message, WPARAM wParam, LPARAM lParam);
#endif
window.cpp
#include "window.h"
bool createWindow(HINSTANCE hInstance)
{
WNDCLASSEX wndClass;
wndClass.cbSize = sizeof(WNDCLASSEX);
wndClass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = messageHandler;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = hInstance;
wndClass.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wndClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wndClass.lpszMenuName = "MAIN_MENU";
wndClass.lpszClassName = "Game Window";
// register the window class
if(!RegisterClassEx(&wndClass))
{
MessageBox(NULL, "Unable to register window class", "Game Window", MB_ICONERROR);
return false;
}
// create the window
if(!(windowHandle = CreateWindowEx(NULL, "Game Window", "Game Window", WS_OVERLAPPEDWINDOW CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0,
hInstance, 0)))
{
MessageBox(NULL, "Unable to create window", "Game Window", MB_ICONERROR);
return false;
}
return true;
}
// makes the window visible
void showWindow(int iShowCmd)
{
if(windowHandle != NULL)
{
ShowWindow(windowHandle, iShowCmd);
UpdateWindow(windowHandle);
}
}
LRESULT CALLBACK messageHandler(HWND wHandle, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_CREATE:
{
//initialize game
return 0;
}
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(wHandle, message, wParam, lParam);
}
main.cpp
#include "window.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int iShowCmd)
{
createWindow(hInstance);
showWindow(iShowCmd);
return 0;
}
In the .h file type the following extern HWND windowHandle; then in the .cpp type HWND windowHandle; This will allow windowHandle to be global in the project. Just include the file with extern wherever you need the variable.
#ifndef GLOBALS_OWNERSHIPextern#end ifstruct {// declare all the gloabl variables here} G;
You can then place the line "#define GLOBALS_OWNERSHIP" in whichever implementation (.cpp) file you want to "own" the gloabls before you include the header ; all other files that include the header will declare the gloabl structure as extern. As an added bonus, all your gloabl variables are collected in a single object (G), and accessible as G.windowHandle, for example.