Re: Window procedure must be reentrant?
It just does what you told it to do: display the time of window creation. Everything else would be some kind of miracle or at least a bug. ;)
If you want it do display the time of the last window creation before this time (and I think that's what you intend to do), you would need some kind of persistant storage for your time tag, as closing the window also shuts down your app.
Re: Window procedure must be reentrant?
You are going to have to collect this info and store it. You can't expect a pointer to stay valid after the execution of the function.
What you have is a severely flawed ideal. You should not have to pass the time through the lparam. You should have a static local map that registers a hwnd to a time struct which is generated when a WM_CREATE message is receive and destroyed when WM_NCDESTROY is received
Re: Window procedure must be reentrant?
What do you mean persistant storage for my time tag? Would you mind giving me a simple example? Thanks.
Quote:
Originally Posted by
Eri523
It just does what you told it to do: display the time of window creation. Everything else would be some kind of miracle or at least a bug. ;)
If you want it do display the time of the last window creation before this time (and I think that's what you intend to do), you would need some kind of persistant storage for your time tag, as closing the window also shuts down your app.
Re: Window procedure must be reentrant?
Quote:
Originally Posted by
LarryChen
What do you mean persistant storage for my time tag? Would you mind giving me a simple example? Thanks.
Well, persistant storage is a wide field. And especially when it's about raw Win32, I'm short of "simple examples" for that. Maybe you could use some file or a registry key?
But if it finally is meant to display saved window creation times during a single app session, Joeman's suggestion looks really promising too.
Re: Window procedure must be reentrant?
I guess the only way to save last time of window creation is to use either registry or file.
Quote:
Originally Posted by
Eri523
Well, persistant storage is a wide field. And especially when it's about raw Win32, I'm short of "simple examples" for that. Maybe you could use some file or a registry key?
But if it finally is meant to display saved window creation times during a single app session, Joeman's suggestion looks really promising too.
Re: Window procedure must be reentrant?
Static variable won't work because after the program exits, the static variable will be destroyed. The only way as Eri523 pointed out is to use either file or registry.
Quote:
Originally Posted by
Joeman
You are going to have to collect this info and store it. You can't expect a pointer to stay valid after the execution of the function.
What you have is a severely flawed ideal. You should not have to pass the time through the lparam. You should have a static local map that registers a hwnd to a time struct which is generated when a WM_CREATE message is receive and destroyed when WM_NCDESTROY is received
Re: Window procedure must be reentrant?
If you do need it longer than the programs life span, you will need to dump this info to a file.
Re: Window procedure must be reentrant?
Your questions are very misleading. You aren't getting the right answers because you aren't asking the right questions. You can't effectively use the hwnd to identify your window from the previous run. It can be different in the next run.
Re: Window procedure must be reentrant?
Quote:
Static variable won't work because after the program exits, the static variable will be destroyed.
The same way window properties are destroyed when you destroy the window. Even if your program is still running and able to create another window instance, it is absolutely different window with its own properties. So you just cannot store something there in props after window death. And your case is definitely a design issue. :)
PS. There was no need in such a complex schema of passing pointer to time_tag in this case. That time_t fits in DWORD and could be just stored in property as it is. Besides, there's no need to snap it before CreateWindow, and it might be inside WM_CREATE handler alright.
Re: Window procedure must be reentrant?
Just to give you an ideal how simple this should be
Code:
#include <windows.h>
#include <fstream>
#include <ctime>
#include <string>
#include <iostream>
using namespace std;
/* Declare Windows procedure */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
/* Make the class name into a global variable */
char szClassName[ ] = "CodeBlocksWindowsApp";
void StoreTime( const string& Name )
{
ofstream OutFile( (Name + "_Last_Run.txt").c_str(), ios::out);
if( OutFile.is_open() )
{
time_t t = time(NULL);
char* s = ctime(&t);
OutFile << s;
}
else
{
throw( "can't open file to write" );
}
}
string GetLastLoadTime( const string& Name )
{
string Time;
ifstream InFile;
InFile.open( (Name + "_Last_Run.txt").c_str(), ios::in );
if( !InFile.is_open() )
{
InFile.close();
StoreTime( Name );
InFile.open( (Name + "_Last_Run.txt").c_str(), ios::in );
if( !InFile.is_open() ) throw( "can't open file to receive last load time" );
}
getline( InFile, Time );
StoreTime( Name );
return Time;
}
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nCmdShow)
{
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 colour 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 */
"Window1", /* 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 */
);
string Time = GetLastLoadTime( "Window1" );
cout << "Last load time was " << Time << endl;
/* Make the window visible on the screen */
ShowWindow (hwnd, nCmdShow);
/* 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;
}
/* This function is called by the Windows function DispatchMessage() */
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) /* handle the messages */
{
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;
}
This was generated with code::blocks and I only added a little code. This is just an example on how to accomplish this. It is by no means the best approach.
Re: Window procedure must be reentrant?
I have a question here. After I call SetProp and GetProp, why'd I need to call RemoveProp since when the program exits the property will be destroyed anyway. What if I don't call RemoveProp? Thanks.
Re: Window procedure must be reentrant?
Because msdn says so. http://msdn.microsoft.com/en-us/libr...8VS.85%29.aspx
Quote:
Remarks
Before a window is destroyed (that is, before it returns from processing the
WM_NCDESTROY message), an application must remove all entries it has added to the property list. The application must use the
RemoveProp function to remove the entries.
Quote:
Originally Posted by LarryChen
What if I don't call RemoveProp?
I am guessing it has to do with properly destroying what these properties contain
Re: Window procedure must be reentrant?
Quote:
Originally Posted by
LarryChen
I have a question here. After I call SetProp and GetProp, why'd I need to call RemoveProp since when the program exits the property will be destroyed anyway. What if I don't call RemoveProp? Thanks.
Just be a good citizen and always call cleanup operations.
Why? You might as well get in the habit of always cleaning up resources properly. Sure it doesn't necessarily matter in this case, but one day sloppy habits will come back to bite you and you spend hours tracking down some problem related to not properly cleaning up resources.