CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 6 of 6
  1. #1
    Join Date
    Jan 2009
    Location
    England
    Posts
    54

    [RESOLVED] Basic Window wrapper

    All the basic programs I've written are for a console. What I am working on is creating a basic window that appears to be a console. Just one window for the time being with a black background with white text and a fixed pitched font (8x8).

    I have created a class CApp() and placed everything in it as a best effort, and I am a beginner with windows.

    The problem I am having is that the program will only run once, when you close the window app the IDE (code blocks) tells me that the compiler/app is still running and I have to close and reboot.

    I want to point out that I have been researching this (google) and I have learned that you can create a Window application using main() instead of WinMain(), so that is what I've done. Either this is the issue or I am not processing a quit message?

    Here is what I've done so far:

    Code:
    // CApp.h
    
    #ifndef WINCON_CAPP_H
    #define WINCON_CAPP_H
    
    
    #if defined(UNICODE) && !defined(_UNICODE)
       #define _UNICODE
    #elif defined(_UNICODE) && !defined(UNICODE)
       #define UNICODE
    #endif
    
    
    #include <windows.h>
    
    
    namespace WinCon {
    
    
    class CApp
    {
    public:
       CApp();
       ~CApp();
    
    
       int  Create();
       void Show();
    
    
       HINSTANCE GetInstance() const { return m_sWinClass.hInstance; }
       LPCSTR GetClassName() const { return m_sWinClass.lpszClassName; }
       HWND GetWindowHandle() const { return m_hWindow; }
    
    
       static LRESULT CALLBACK WinProc(HWND hwnd , UINT message,
                                       WPARAM wParam, LPARAM lParam);
    
    
    protected:
       void SetInstance();
       int  RegisterClass(WNDCLASSEX *winClass);
    
    
    private:
       HWND m_hWindow;
       WNDCLASSEX m_sWinClass;
    };
    
    
    } // namespace WinCon
    
    
    #endif // WINCON_CAPP_H
    Code:
    // CApp.cpp
    #include "CApp.h"
    
    
    using namespace WinCon;
    
    
    CApp::CApp() : m_hWindow(NULL)
    {
       SetInstance();
    
    
       m_sWinClass.lpszClassName = "WinCon";
       m_sWinClass.lpfnWndProc = WinProc;
       m_sWinClass.style = CS_DBLCLKS;
       m_sWinClass.cbSize = sizeof(WNDCLASSEX);
       m_sWinClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
       m_sWinClass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
       m_sWinClass.hCursor = LoadCursor(NULL, IDC_ARROW);
       m_sWinClass.lpszMenuName = NULL;
       m_sWinClass.cbClsExtra = 0;
       m_sWinClass.cbWndExtra = 0;
       m_sWinClass.hbrBackground = (HBRUSH) COLOR_BACKGROUND; // black ?
    
    
       RegisterClass(&m_sWinClass);
    
    
    }
    
    CApp::~CApp() {}
    
    void CApp::SetInstance()
    {
       if((m_sWinClass.hInstance = GetModuleHandle(NULL)) == NULL) {
          MessageBox(NULL, TEXT("Unable to obtain the program instance."),
                     TEXT("WinCon Error - CApp::SetInstance()"),
                     MB_ICONSTOP | MB_OK | MB_TASKMODAL);
       }
    }
    
    int CApp::RegisterClass(WNDCLASSEX *winClass)
    {
       if(!RegisterClassEx(winClass)) {
          MessageBox(NULL, TEXT("Window registration failed."),
                     TEXT("WinCon Error - CApp::RegisterClass()"),
                     MB_ICONSTOP | MB_OK | MB_TASKMODAL);
    
    
          return 1;
       }
    
    
       return 0;
    }
    
    int CApp::Create()
    {
       m_hWindow = CreateWindowEx(
          0,                    // Extended window style
          GetClassName(),       // Pointer to registered class name
          TEXT("WinCon App"),   // Pointer to window name
          WS_OVERLAPPEDWINDOW,  // Window style
          CW_USEDEFAULT,        // Horizontal position of window
          CW_USEDEFAULT,        // Vertical position of window
          544,                  // Window width
          375,                  // Window height
          HWND_DESKTOP,         // Handle to parent or owner window
          NULL,                 // Handle to menu, or child-window identifier
          GetInstance(),        // Handle to program instance
          NULL                  // Pointer to window-creation data
       );
    
    
       if(!m_hWindow) {
          MessageBox(NULL, TEXT("Window creation failed."),
                     TEXT("WinCon Error - CApp::Create()"),
                     MB_ICONSTOP | MB_OK | MB_TASKMODAL);
    
    
          return 1;
       }
    
    
       return 0;
    }
    
    void CApp::Show()
    {
       ShowWindow(m_hWindow, SW_SHOWDEFAULT);
       UpdateWindow(m_hWindow);
    }
    
    LRESULT CALLBACK CApp::WinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
       switch(message) {
          case WM_DESTROY:
             PostQuitMessage(0);
             break;
    
    
          default:
             return DefWindowProc(hwnd, message, wParam, lParam);
       }
    
    
       return 0;
    }
    And main like this:

    Code:
    #include "CApp.h"
    
    
    using namespace WinCon;
    
    
    int main()
    {
       CApp myConsole;
    
    
       myConsole.Create();
       myConsole.Show();
    
    
       MSG msg;
    
    
       while(GetMessage(&msg, myConsole.GetWindowHandle(), 0, 0)) {
          TranslateMessage(&msg);
          DispatchMessage(&msg);
       }
    
    
       return (int) msg.wParam;
    }
    I hope someone will explain what I've done wrong and how I can resolve this. Any further advice is welcome.
    What the mind can conceive it can achieve.

  2. #2
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,607

    Re: Basic Window wrapper

    PostQuitMessage function
    Remarks

    The PostQuitMessage function posts a WM_QUIT message to the thread's message queue and returns immediately; the function simply indicates to the system that the thread is requesting to quit at some time in the future.

    When the thread retrieves the WM_QUIT message from its message queue, it should exit its message loop and return control to the system. The exit value returned to the system must be the wParam parameter of the WM_QUIT message.
    But you pump your window messages only. Try use NULL instead of myConsole.GetWindowHandle().

    EDIT: Ah, and please make sure WM_DESTROY is really received.
    Last edited by Igor Vartanov; August 21st, 2015 at 03:04 AM.
    Best regards,
    Igor

  3. #3
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,607

    Re: Basic Window wrapper

    Besides,

    Code:
       while(GetMessage(&msg, myConsole.GetWindowHandle(), 0, 0)) {
          TranslateMessage(&msg);
          DispatchMessage(&msg);
       }
    This does not handle situations when GetMessage() returns -1. A very typical beginner's miss.

    Should be something like this:
    Code:
       while(0 < GetMessage(&msg, NULL, 0, 0)) {
          TranslateMessage(&msg);
          DispatchMessage(&msg);
       }
    Last edited by Igor Vartanov; August 21st, 2015 at 03:05 AM.
    Best regards,
    Igor

  4. #4
    Join Date
    Jan 2009
    Location
    England
    Posts
    54

    Re: Basic Window wrapper

    I can't thank you enough, it works fine now. I understand your changes in the message loop and I've been looking up the functions and reading about the return values and remarks, don't understand all of it at this time however.

    As far as I can see I have handled WM_DESTROY correctly? Have I missed something?

    Code:
    LRESULT CALLBACK CApp::WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
       switch(msg) {
          case WM_DESTROY:
             PostQuitMessage(0);
             break;
    
    
          default:
             return DefWindowProc(hwnd, msg, wParam, lParam);
       }
    
    
       return 0;
    }

    I have made a couple of changes to the code. In function RegisterClass() I have changed the return value order so it looks like all the other examples I have seen.

    Code:
    int CApp::RegisterClass(WNDCLASSEX *winClass)
    {
       if(!RegisterClassEx(winClass)) {
          MessageBox(NULL, TEXT("Window registration failed."),
                     TEXT("WinCon Error - CApp::RegisterClass()"),
                     MB_ICONSTOP | MB_OK | MB_TASKMODAL);
    
    
          return 0;
       }
    
    
       return 1;
    }
    The issue I have is that I never use the return value so could I get away with making this function void and not return anything? Or is the return 0 going somewhere else?

    Likewise I changed Create() to return 0 on failure and the same thought as with RegisterClass() comes to mind?


    Code:
    // The bit in Create() I've changed.....
    
    if(!m_hWindow) {
          MessageBox(NULL, TEXT("Window creation failed."),
                     TEXT("WinCon Error - CApp::Create()"),
                     MB_ICONSTOP | MB_OK | MB_TASKMODAL);
    
    
          return 0;
       }
    
    
       return 1;
    }
    I'm sure you see my point here?
    Last edited by Gerald Bates; August 21st, 2015 at 09:57 AM.
    What the mind can conceive it can achieve.

  5. #5
    Join Date
    Jan 2009
    Location
    England
    Posts
    54

    Re: Basic Window wrapper

    I have tested this and it does appear to be working so I am leaving the code as it is. Sorry for the silly questions but I really don't understand much about windows programming.


    My next issue is trying to get "Hello World!" displayed on the screen, the text should be in white on a black background but I am getting a window background in black but for the length of the string only I get a white background and black text?


    In the CApp() c'tor I have done this:


    Code:
       
    m_sWinClass.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);

    In CApp.cpp I've added this:


    Code:
    HDC hDc;
       HBRUSH hBrush;
    
    
       switch(msg) {
          case WM_CREATE:
             hDc = GetDC(hwnd);
             hBrush = (HBRUSH) GetStockObject(ANSI_FIXED_FONT);
    
    
             SetTextColor(hDc, RGB(255, 255, 255)); // White text.
    
    
             SelectObject(hDc, hBrush);
             DeleteObject(hBrush);
             ReleaseDC(hwnd, hDc);
             break;

    In my main.cpp I have done this:

    Code:
    #include "CApp.h"
    #include <cstring>
    #include <cstdio>
    
    
    using namespace WinCon;
    
    
    int main()
    {
       CApp myConsole;
    
    
       myConsole.Create();
       myConsole.Show();
    
    
       MSG msg;
       char str[255];
    
    
       HDC hDc = GetDC(myConsole.GetWindowHandle());
       sprintf(str, "Hello World!");
       TextOut(hDc, 10, 10, str, strlen(str));
       ReleaseDC(myConsole.GetWindowHandle(), hDc);
    
    
       while(0 < GetMessage(&msg, NULL, 0, 0)) {
          TranslateMessage(&msg);
          DispatchMessage(&msg);
       }
    
    
       return msg.wParam;
    }

    Why is the text colour and background wrong? Have I got a fixed pitch font properly
    or should I use another function?
    What the mind can conceive it can achieve.

  6. #6
    Join Date
    Jan 2009
    Location
    England
    Posts
    54

    Re: Basic Window wrapper

    I have decided to study a bit more and write simple window programs without using classes. Many thanks for the advice given, it is appreciated.
    What the mind can conceive it can achieve.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured