Skip to main content
gamedev.net
🔒 Locked

MessageBox causing errors?

Started by Tonin Nov 1, 2005 at 9:00 PM 4 replies 650+ views
Original Post
Tonin
Tonin
Hi, I'm trying to build a small c++ class to log errors and events. It's coming along pretty well, but I've run into a weird bug that I can't figure out. Basically what happens is that if you use the class in the window proc it somehow corrupts the object and from then on it logs some of the data wrong (it puts multiple entries on the same line and makes double entries). This only happens with the K_USER_***** versions (which have a call to MessageBox in them), and only when a call to the logger is made at the beginning of the win proc, before the switch statement. If you comment out that call then every thing works the way it should. Here is the code for my class and the main cpp file: main.cpp
#include <windows.h>


#include "klog.h"

Klog logger;



/*  This function is called by the Windows function DispatchMessage()  */
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{

    // if you comment this out then it works ok.
    logger<<"Message: " <<message <<K_EVENT;


    switch (message)                  /* handle the messages */
    {
        // this dosn't work right when the above call is in place.
        case WM_RBUTTONUP:
             logger<<"Right button up" <<K_USER_EVENT;
             break;


        case WM_DESTROY:
             PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
             break;

        default:                      /* for messages that we don't deal with */
             return DefWindowProc (hwnd, message, wParam, lParam);
    }

    return 0;
}







/*  Make the class name into a global variable  */
char szClassName[ ] = "WindowsApp";

int WINAPI WinMain (HINSTANCE hThisInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpszArgument,
                    int nFunsterStil)

{
    HWND hwnd;               /* This is the handle for our window */
    MSG messages;            /* Here messages to the application are saved */
    WNDCLASSEX wincl;        /* Data structure for the windowclass */

    /* The Window structure */
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
    wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
    wincl.cbSize = sizeof (WNDCLASSEX);

    /* Use default icon and mouse-pointer */
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;                 /* No menu */
    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default color as the background of the window */
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    /* Register the window class, and if it fails quit the program */
    if (!RegisterClassEx (&wincl))
        return 0;

    /* The class is registered, let's create the program*/
    hwnd = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           szClassName,         /* Classname */
           "Windows App",       /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           544,                 /* The programs width */
           375,                 /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           hThisInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );

    /* Make the window visible on the screen */
    ShowWindow (hwnd, nFunsterStil);

    /* Run the message loop. It will run until GetMessage() returns 0 */
    while (GetMessage (&messages, NULL, 0, 0))
    {
        /* Translate virtual-key messages into character messages */
        TranslateMessage(&messages);
        /* Send message to WindowProcedure */
        DispatchMessage(&messages);
    }

    /* The program return-value is 0 - The value that PostQuitMessage() gave */
    return messages.wParam;
}


Klog.h
#ifndef KLOG_H
#define KLOG_H

#include <windows.h>

#include <sstream>
#include <fstream>
#include <string>


// used as commands you passs to the Klog
enum KCON
{
     K_ERROR,
     K_EVENT,
     K_USER_ERROR,
     K_USER_EVENT
};



class Klog
{
private:

     std::string buffer;
     
     // writes the contents of buffer to a file.
     bool write(std::string fileName);

public:

     Klog();

     // adds stuff to the buffer.
     template<typename T>
     Klog& operator << (T data)
     {
          std::ostringstream ss;
          ss<<data;
          buffer += ss.str();
          return *this;
     }

     // prosseses commands..
     Klog& operator << (KCON cmd);
};


#endif


Klog.cpp
#include "klog.h"


// clean out the log files on startup..
Klog::Klog()
{
     std::ofstream file;

     file.open("event_log.txt", std::ios::out | std::ios::trunc);
     file<<"event_log\n";
     file.close();
     file.open("error_log.txt", std::ios::out | std::ios::trunc);
     file<<"error_log\n";
     file.close();
}


// write the buffer to a file
bool Klog::write(std::string fileName)
{
     std::ofstream file;

     file.open(fileName.c_str(), std::ios::out | std::ios::app);
     if(!file.is_open())
          return false;


     file << buffer <<"\n";

     file.close();

     return true;
}



// prossess any commands sent to the Klog..
Klog& Klog::operator << (KCON cmd)
{
     switch (cmd)
     {
          case K_EVENT:   // log it.
          {
               write("event_log.txt");
               buffer.clear();
          }
          break;
          case K_ERROR:   // log it.
          {
               write("error_log.txt");
               buffer.clear();
         }
          break;
          case K_USER_EVENT:    // log it and pop a box.
          {
               write("event_log.txt");
               MessageBox(NULL,buffer.c_str(),"Event",MB_OK);
               buffer.clear();
          }
          break;
          case K_USER_ERROR:    // log it and pop a box.
          {
               write("error_log.txt");
               MessageBox(NULL,buffer.c_str(),"Error",MB_OK);
               buffer.clear();
          }
          break;
     }

     return *this;
}



I think it has something to do with the MessageBox call, which seems to be messing with the Klog class in some way I don't understand. If you watch buffer with a debugger, it gets emptied after the MessageBox call, but before the call to buffer.clear(). I've tried isolating buffer from the actual MessageBox call by moving the contents of buffer to a temp array and passing that into MessageBox, but it still screws it up. This is easy to get around, just don't call the logger at the top of the win proc, but its been driving me crazy trying to figure it out. I'd really like to know what's going on, but haven't been able to work it out on my own so far. Any comments or suggestions would be great, ~Andy
Skeleton_V@T
Skeleton_V@T
I don't see any problem with the log file, here's the result of eventlog.txt (cut down some parts):

event_log
Message: 36
Message: 129
Message: 1
Message: 134
//...
Right button up
Right button upMessage: 134
Message: 13
Message: 6
//...
Message: 8
Message: 641

Is that considered okay ? :/
--> The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones <--
iMalc
iMalc
I seriously recommend you don't use MessageBox from inside your WindowProc, or any kind of callback function.
I know that it can totaly wreak havoc on your app, which no doubt you've now also learned.
Tonin
Tonin
Skeleton_V@T, That log does show the error I was talking about,

//...
Right button up
Right button upMessage: 134
Message: 13
Message: 6
//...

Should be:

//...
Right button up
Message: 134
Message: 13
Message: 6
//...

If it was working properly.



iMalc, Do you mean just in the actual callback or also in functions called from inside it? I'm kind of new to it, but isn't most of the code in a win32 program called from the win proc in response to messages?



AP, it compiles (and seems to work) fine for me (Dev-C++ 4.9.9.2). I'm no expert on templates though, Could you suggest a more appropriate way of doing it for me?


Thanks for the replies,
~Andy

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.