Help with getting a window to display

Started by
7 comments, last by Scheermesje 19 years, 8 months ago
I was going through the forger's win32 API tutorial, and I thought "hey, I'll be clever and put all this stuff into special functions", well it doesn't work and I think knowing why would help with my C skills. Main.cpp

#define WIN32_LEAN_AND_MEAN //Cuts the crap
//Includes//////////////////////////////////////////////////////////////////////
#include "Functions.h"
//WinMain///////////////////////////////////////////////////////////////////////
int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow)
{
    MSG Msg;
    
    CreateMyWindClass();
    CreateMyWindow();
    
    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}


Functions.cpp

//FunctionDefinitions///////////////////////////////////////////////////////////
//Main Window Procedure/////////////////////////////////////////////////////////
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
        case WM_CLOSE:
        {
            DestroyWindow(hwnd);
            break;
        }
        
        case WM_DESTROY:
        {
            PostQuitMessage(0);
            break;
        }
        
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

//CreateWindClass///////////////////////////////////////////////////////////////
int CreateMyWindClass()
{
    //wc is static, so there's no need for a return value, just use wc
    static WNDCLASSEX wc;
    extern HINSTANCE hInstance;
    extern char g_szClassName[];

    //Registering the Window Class
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = 0;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = g_szClassName;
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

    if(!RegisterClassEx(&wc))
    {
        MessageBox(NULL, "Window Registration Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }
    return 1;
}

int CreateMyWindow()
{
    extern HINSTANCE hInstance;
    extern int nCmdShow;
    extern char g_szClassName[];

    static HWND hwnd;
    hwnd = CreateWindowEx(
        WS_EX_CLIENTEDGE,
        g_szClassName,
        "The title of my window",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
        NULL, NULL, hInstance, NULL);

    if(hwnd == NULL)
    {
        MessageBox(NULL, "Window Creation Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 1;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);
}



and Functions.h

#ifndef FUNCTIONS_H
#define FUNCTIONS_H
////////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include "Functions.cpp"
//Consts////////////////////////////////////////////////////////////////////////
const char g_szClassName[] = "myWindowClass";
//FunctionDeclarations//////////////////////////////////////////////////////////
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
int CreateMyWindClass();
int CreateMyWindow();

#endif


the linker says:

Functions.o(.text+0x0):Functions.cpp: multiple definition of `_Z7WndProcP6HWND__jjl@16'
main.o(.text+0x0):main.cpp: first defined here
Functions.o(.text+0x80):Functions.cpp: multiple definition of `CreateMyWindClass()'
main.o(.text+0x80):main.cpp: first defined here
Functions.o(.text+0x192):Functions.cpp: multiple definition of `CreateMyWindow()'
main.o(.text+0x192):main.cpp: first defined here
main.o(.text+0xb9):main.cpp: undefined reference to `hInstance'
main.o(.text+0x19c):main.cpp: undefined reference to `hInstance'
main.o(.text+0x1ff):main.cpp: undefined reference to `nCmdShow'
Functions.o(.text+0xb9):Functions.cpp: undefined reference to `hInstance'
Functions.o(.text+0x19c):Functions.cpp: undefined reference to `hInstance'
Functions.o(.text+0x1ff):Functions.cpp: undefined reference to `nCmdShow'
I don't redefine anythng at all, and I don't know where my undefined references are coming from. I thought I defined everything. And yes, I chose Win32 GUI project, not console. [Edited by - Drakkcon on August 3, 2004 1:00:20 AM]
Advertisement
Quote:
#include "Functions.cpp"

You should never need to #include a source file in another source file. Just include a header which declares the function.
You see, this is something that you'd think after all of the tutorials that I've read, I would pick up on this. Thank you for stating this. As I've stated before my knowledge is incrediably spotty.
This doesn't make any sense, look at all the errors I get now:

Functions.cpp:3: parse error before `(' token
Functions.cpp: In function `int CreateMyWindClass()':
Functions.cpp:29: ISO C++ forbids declaration of `WNDCLASSEX' with no type
Functions.cpp:29: parse error before `;' token
Functions.cpp:30: ISO C++ forbids declaration of `HINSTANCE' with no type
Functions.cpp:30: parse error before `;' token
Functions.cpp:34: `wc' undeclared (first use this function)
Functions.cpp:34: (Each undeclared identifier is reported only once for each
function it appears in.)
Functions.cpp:36: `WndProc' undeclared (first use this function)
Functions.cpp:39: `hInstance' undeclared (first use this function)
Functions.cpp:40: `NULL' undeclared (first use this function)
Functions.cpp:40: `IDI_APPLICATION' undeclared (first use this function)
Functions.cpp:40: `LoadIcon' undeclared (first use this function)
Functions.cpp:41: `IDC_ARROW' undeclared (first use this function)
Functions.cpp:41: `LoadCursor' undeclared (first use this function)
Functions.cpp:42: `HBRUSH' undeclared (first use this function)
Functions.cpp:42: `COLOR_WINDOW' undeclared (first use this function)
Functions.cpp:47: `RegisterClassEx' undeclared (first use this function)
Functions.cpp:50: `MB_ICONEXCLAMATION' undeclared (first use this function)

Functions.cpp:50: `MB_OK' undeclared (first use this function)

Functions.cpp:50: `MessageBox' undeclared (first use this function)

Functions.cpp: In function `int CreateMyWindow()':
Functions.cpp:58: ISO C++ forbids declaration of `HINSTANCE' with no type
Functions.cpp:58: parse error before `;' token
Functions.cpp:62: ISO C++ forbids declaration of `HWND' with no type
Functions.cpp:62: parse error before `;' token
Functions.cpp:63: `hwnd' undeclared (first use this function)
Functions.cpp:64: `WS_EX_CLIENTEDGE' undeclared (first use this function)
Functions.cpp:67: `WS_OVERLAPPEDWINDOW' undeclared (first use this function)
Functions.cpp:68: `CW_USEDEFAULT' undeclared (first use this function)
Functions.cpp:69: `CreateWindowEx' undeclared (first use this function)
Functions.cpp:78: `ShowWindow' undeclared (first use this function)
Functions.cpp:79: `UpdateWindow' undeclared (first use this function)

I see no parse error.

EDIT: Updated code to reflect changes.
You are not including "functions.h" in functions.cpp so you are also not including windows.h

You need to add to following code also to your functions.cpp
//Includes//////////////////////////////////////////////////////////////////////#include "Functions.h"


And Sneftel pointed out remove the include ***.cpp line from your header file :)

The cpp file should include the header file not the other way around.
I'm still getting the same errors.
Main.cpp includes functions.h, functions.h includes windows.h, and functions.cpp includes functions.h (which I don't understand).
I've changed your code.. the following code works in VC++.NET 2003.

Main.cpp:

#define WIN32_LEAN_AND_MEAN //Cuts the crap//Includes//////////////////////////////////////////////////////////////////////#include "Functions.h"//WinMain///////////////////////////////////////////////////////////////////////HINSTANCE g_hInstance;int g_nCmdShow;int WINAPI WinMain(HINSTANCE hInstance,                   HINSTANCE hPrevInstance,                   LPSTR lpCmdLine,                   int nCmdShow){    MSG Msg;    	g_nCmdShow = nCmdShow;	g_hInstance = hInstance;    CreateMyWindClass();    CreateMyWindow();        while(GetMessage(&Msg, NULL, 0, 0) > 0)    {        TranslateMessage(&Msg);        DispatchMessage(&Msg);    }    return Msg.wParam;}


Functions.cpp
#include "Functions.h"//FunctionDefinitions/////////////////////////////////////////////////////////////Main Window Procedure/////////////////////////////////////////////////////////LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){    switch(msg)    {        case WM_CLOSE:        {            DestroyWindow(hwnd);            break;        }                case WM_DESTROY:        {            PostQuitMessage(0);            break;        }                default:            return DefWindowProc(hwnd, msg, wParam, lParam);    }    return 0;}//CreateWindClass///////////////////////////////////////////////////////////////int CreateMyWindClass(){    //wc is static, so there's no need for a return value, just use wc    WNDCLASSEX wc;       	//Registering the Window Class    wc.cbSize        = sizeof(WNDCLASSEX);    wc.style         = 0;    wc.lpfnWndProc   = WndProc;    wc.cbClsExtra    = 0;    wc.cbWndExtra    = 0;    wc.hInstance     = g_hInstance;    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);    wc.lpszMenuName  = NULL;    wc.lpszClassName = g_szClassName;    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);    if(!RegisterClassEx(&wc))    {        MessageBox(NULL, "Window Registration Failed!", "Error!",            MB_ICONEXCLAMATION | MB_OK);        return 0;    }    return 1;}int CreateMyWindow(){    HWND hwnd;    hwnd = CreateWindowEx(        WS_EX_CLIENTEDGE,        g_szClassName,        "The title of my window",        WS_OVERLAPPEDWINDOW,        CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,        NULL, NULL, g_hInstance, NULL);    if(hwnd == NULL)    {        MessageBox(NULL, "Window Creation Failed!", "Error!",            MB_ICONEXCLAMATION | MB_OK);        return 1;    }    ShowWindow(hwnd, g_nCmdShow);    UpdateWindow(hwnd);}


Functions.h
#ifndef FUNCTIONS_H#define FUNCTIONS_H////////////////////////////////////////////////////////////////////////////////#include <windows.h>//Consts////////////////////////////////////////////////////////////////////////const char g_szClassName[] = "myWindowClass";//FunctionDeclarations//////////////////////////////////////////////////////////LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);int CreateMyWindClass();int CreateMyWindow();extern HINSTANCE g_hInstance;extern int g_nCmdShow;#endif


I think you need to do some research on the following subjects:

the scope of a variable
the meaning of 'extern'
when and how to include header files

Good luck with it :) Let me hear it if you got any questions.
Oh, you put external devclarations in the header files. That explains it. Thanks.

BUT. If WNDCLASSX isn't static, doesn't that mean it will fall out of scope after the function call?

OH, but the class is registered. I gotcha now.
wndclassx will fal out of function scope but as you said it doesn't matter because you used it :)

If you would be calling a function every frame and you need to keep the value the same between all the function calls you need to declare it static. Otherwise you won't need it :)

As a practice.. try to encapsulate your functions in a class. Give the class an init function(or how you want to name it) and give the hinstance and nCmdShow as parameters.

Write the class once and use it often :)

You could also give it a boolean value for fullscreen yes/no.

This topic is closed to new replies.

Advertisement