WinAPI newbie requesting assistance with WindowProc (and other stuff)

I'm trying to make a utility that will log all power messages (and eventually do some other cool stuff, but for now I'm focusing on that). However, I'm painfully green when it comes to WinAPI, and although I've been reading up on it all month, I'm still not confident I understand what's going on in what I've done so far. Much of what I've done is more or less copied and pasted from tutorials that I only understand in a rudimentary sense.

My code has a callback function "WndProc" with a case switch for types of the message WM_POWERBROADCAST. Currently, for each case, it will create a new log file and write data into that log. But what I want to do is make it append an existing log. Is there some way to feed this WndProc function a local ofstream pointer? I could probably just declare this ofstream globally, but I think that's asking for multithreading-related trouble. Is there a better way to accomplish what I'm trying to do?

Also, if there are any miscellaneous bone-headed moves I'm making, especially ones related to WinAPI stuff, I would greatly appreciate being informed of them.

My code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181

#include "tchar.h"

#include <fstream>
#include <iostream>
#include <windows.h>

#include "time.h"

using namespace std;

void open_new_log(ofstream &);
void get_utc_time(char *);
void get_local_time(char *);
void log_PMM(ofstream &, string);

bool FILENAMES_USE_UTC = true;

LPCWSTR g_szClassName = _T("myWindowClass");

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
		case WM_POWERBROADCAST:
		{
			switch(wParam)
			{
				case PBT_APMRESUMEAUTOMATIC:
				{
					MessageBox(hwnd, _T("System resumed automatically."), _T("Alert!"), MB_OK);
					ofstream logfile;
					open_new_log(logfile);
					log_PMM(logfile, "PBT_APMRESUMEAUTOMATIC");
					logfile.close();
				}
				break;

				case PBT_APMRESUMESUSPEND:
				{
					MessageBox(hwnd, _T("System resumed by user input."), _T("Alert!"), MB_OK);
					ofstream logfile;
					open_new_log(logfile);
					log_PMM(logfile, "PBT_APMRESUMESUSPEND");
					logfile.close();
				}
				break;

				case PBT_APMSUSPEND:
				{
					MessageBox(hwnd, _T("System suspended."), _T("Alert!"), MB_OK);
					ofstream logfile;
					open_new_log(logfile);
					log_PMM(logfile, "PBT_APMSUSPEND");
					logfile.close();
				}
				break;
			}
		}
        break;
        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
        break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{

	ofstream logfile;
	open_new_log(logfile);

	// initialize window
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    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, _T("Window Registration Failed!"), _T("Error!"),
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    hwnd = CreateWindowEx(
        WS_EX_CLIENTEDGE,
        g_szClassName,
        NULL,
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
        NULL, NULL, NULL, NULL);

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


	// main loop
	while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
	}
	
	logfile.close();
	return Msg.wParam;

}

/*
	Creates and opens a new log file, using current time as a name
*/
void open_new_log(ofstream &logfile)
{
	char buffer[80];

	if (FILENAMES_USE_UTC)
	{
		get_utc_time(buffer);
	}
	else
	{
		get_local_time(buffer);
	}

	strcat_s(buffer, 80, ".log");

	logfile.open(buffer);

}

void get_utc_time(char *buffer)
{
	SYSTEMTIME st;
	GetSystemTime(&st);
	sprintf_s(buffer, 80, "%04d%02d%02dT%02d%02d%02d%03dZ", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
}

void get_local_time(char *buffer)
{
		time_t rawtime;
		struct tm timeinfo;
		time ( &rawtime );
		localtime_s(&timeinfo, &rawtime );
		strftime (buffer,80,"%Y%m%dT%H%M",&timeinfo);
}


/*
	Writes power management message to the open log file
*/
void log_PMM(ofstream &logfile, string PMM)
{
	char buffer[80];

	get_local_time(buffer);
	logfile << "Time: " << buffer << "\nType: Power Message\nData: " << PMM.c_str() << "\n";
}
Instead of creating the filename at runtime, give it a hardcoded name and then keep on appending text to it by opening it in ios::app mode. Otherwise, you can create a static file stream object in winproc and use it again and again without changing it and then can close it WM_CLOSE or WM_DESTROY.
Hi ikantspelwurds,

I'd have liked to have run your program, but couldn't get it to compile. Piles of errors. Does yours compile? What development environment/compiler you using? I tried on Dev-C++. I also have CodeBlocks, VC6 and VC9, but I didn't try those. I'm fairly experienced at Win32, but never fooled with power messages. That's why it interested me.
Instead of creating the filename at runtime, give it a hardcoded name and then keep on appending text to it by opening it in ios::app mode.

The program needs to be capable of writing a new log file whenever the current one gets too big. Naming it after the current time seemed like the simplest way to ensure no two files have the same name.

Otherwise, you can create a static file stream object in winproc and use it again and again without changing it and then can close it WM_CLOSE or WM_DESTROY.

Is that thread-safe? If so, how do you do that? I'm not really sure what I'm doing in winproc - I mainly just screwed around with the function until I got something that appeared to work.

Does yours compile? What development environment/compiler you using? I tried on Dev-C++.

It compiles fine and runs as described. I'm using VC9 Standard, and compiling using the Windows 7 SDK. As far as I know, VC9 express should work too.
Last edited on
for file name, use a naming convention and append a time-stamp with it. this will free you from name clashing. when the file gets big, make a new file with new time-stamp.

If your application is multi-threaded, you need to sync the write to the file.
Otherwise, you have written a separate function for writing to the file. just change it to pass only the string. open the stream inside the function only. like this:

1
2
3
4
5
6
7
8
void log_PMM(string FileName, string PMM)
{
	char buffer[80];
	ofstream ofs(FileName.c_str());
	get_local_time(buffer);
	ofs << "Time: " << buffer << "\nType: Power Message\nData: " << PMM.c_str() << "\n";
	ofs.close();
}


Save the FileName in your winproc and keep changing it as soon you create a new file. Dont open file stream at every place in the program.

1
2
3
4
5
6
7
8
9
10
11
12
windproc()
{
static string FileName;

//i want to open a new file, update the FileName
FileName = MakeNewFileName();
..

...
log_PMM(FileName, StringToWrite);

}

Last edited on
Topic archived. No new replies allowed.