Note: Overcoming WinMain’s ANSI lpCmdLine

هذه المقالة متوفرة أيضا باللغة العربية، اقرأها هنا.

I got a question about WinMain and its ANSI lpCmdLine. Are you required to use the ANSI argument? No, you are not!

For unknown reason, WinMain and also main functions come with only ANSI command-line arguments (lpCmdLine in WinMain and argv in main.) To overcome this situation, you can forget about function arguments and use the function GetCommandLine to get a pointer to the command-line string for the current process.

The definition for this function is as follows:

LPTSTR GetCommandLine(VOID)

Simple, isn’t it?

Simulating CWinApp::OnIdle in C

هذه المقالة متوفرة أيضا باللغة العربية، اقرأها هنا.

MFC allows you to override CWinApp::OnIdle function to perform idle-time processing.

This function is called whenever there’re no messages are waiting for processing in the message queue.

In this function, you can perform some secondary processing like updating the status bar, toolbar, etc.

The definition of this function is as follows:

virtual BOOL OnIdle(LONG lCount);

If you are interested you can override this function and do some processing. The following example paints random rectangle while the application is idle (that is no processing is carried on.) Thus, this code doesn’t make the application irresponsive.

	BOOL OnIdle(LONG lCount)
	{
		CWinApp::OnIdle(lCount);

		CClientDC dc(m_pMainWnd);
		RECT rct;

		m_pMainWnd->GetClientRect(&rct);
		SetRect(&rct,
			rand() % rct.right,
			rand() % rct.bottom,
			rand() % rct.right,
			rand() % rct.bottom);

		dc.Rectangle(&rct);
		return TRUE;
	}

This function receives only a single argument, lCount; it contains a value incremented each time OnIdle is called, and it is reset to 0 each time a new session is established. A new session is established each time your application finishes processing pending messages and no messages are left.

MFC continues to call CWinApp::OnIdle (incrementing lCount each time) as long as there’re no messages are waiting for processing. If the application received a new message, MFC ends the current session and stops calling OnIdle until it establishes a new session again. If you want, you can return TRUE to indicate that further processing is required and MFC should call OnIdle again (as long as we are in the current session,) or FALSE to indicate that processing have been finished and MFC should not call OnIdle again until a new session is established.

Notice that, you should call the base implementation of CWinApp::OnIdle because that the default implementation of OnIdle updates command UI objects like menu items and toolbars besides doing some internal structure cleanup.

Unfortunately, C doesn’t include OnIdle function. However, we could work out ours.

The following C example shows our new handmade message queue that simulates CWinApp::OnIdle:

	while (TRUE) {
		if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {

			// if a quit message
			if (WM_QUIT == msg.message)
				break; // exit the loop

			// process other messages
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else {	// no messages are waiting
			// do some idle processing
		}
	}

The key function is PeekMessage. This function checks the message queue and if a message was found it removes the message from the queue (if PM_REMOVE specified,) initializes the MSG object with message data, and returns TRUE to the caller. If no message was found, PeekMessage returns FALSE thus executing the code (secondary processing) in the else statement.

You can also create your fully-featured handmade OnIdle. Consider the following code:

BOOL OnIdle(LONG lCount);

int WINAPI WinMain(. . .)
{
	MSG msg;
	LONG lCount;

	. . .

	while (TRUE) {
		if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
			// found a message, resetting
			lCount = 0;

			if (WM_QUIT == msg.message)
				break;

			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else {
			if (lCount >= 0) {
				if (!OnIdle(lCount)) {
					// set a flag indicates
					// no further OnIdle
					// calls till a new
					// session
					lCount = -1;
				}

				// increment the counter
				lCount++;
			}
		}
	}

	return msg.wParam;
}

BOOL OnIdle(LONG lCount)
{
	/*

	do some processing

	*/

	return FALSE;
}

Have a nice day!