// --------------------------------------------------------------------------
// Window 2: Display increasing sequence of prime numbers
// --------------------------------------------------------------------------
LRESULT APIENTRY WndProc2 (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static int iNum = 1, iLine, cyClient ;
HDC hdc ;
int i, iSqrt ;
TCHAR szBuffer[16] ;
switch (message)
{
case WM_SIZE:
cyClient = HIWORD (lParam) ;
return 0 ;
case WM_TIMER:
do {
if (++iNum < 0)
iNum = 0 ;
iSqrt = (int) sqrt (iNum) ;
for (i = 2 ; i <= iSqrt ; i++)
if (iNum % i == 0)
break ;
}
while (i <= iSqrt) ;
iLine = CheckBottom (hwnd, cyClient, iLine) ;
hdc = GetDC (hwnd) ;
TextOut ( hdc, 0, iLine * cyChar, szBuffer,
wsprintf (szBuffer, TEXT ("%d"), iNum)) ;
ReleaseDC (hwnd, hdc) ;
iLine++ ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
// --------------------------------------------------------------------------
// Window 3: Display increasing sequence of Fibonacci numbers
// --------------------------------------------------------------------------
LRESULT APIENTRY WndProc3 (HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam)
{
static int iNum = 0, iNext = 1, iLine, cyClient ;
HDC hdc ;
int iTemp ;
TCHAR szBuffer[16] ;
switch (message)
{
case WM_SIZE:
cyClient = HIWORD (lParam) ;
return 0 ;
case WM_TIMER:
if (iNum < 0)
{
iNum = 0 ;
iNext = 1 ;
}
iLine = CheckBottom (hwnd, cyClient, iLine) ;
hdc = GetDC (hwnd) ;
TextOut ( hdc, 0, iLine * cyChar, szBuffer,
wsprintf (szBuffer, "%d", iNum)) ;
ReleaseDC (hwnd, hdc) ;
iTemp = iNum ;
iNum = iNext ;
iNex += iTemp ;
iLine++ ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
// --------------------------------------------------------------------------
// Window 4: Display circles of random radii
// ---------------------------------------------------------------------------
LRESULT APIENTRY WndProc4 (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static int cxClient, cyClient ;
HDC hdc ;
int iDiameter ;
switch (message)
{
case WM_SIZE:
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
return 0 ;
case WM_TIMER:
InvalidateRect (hwnd, NULL, TRUE) ;
UpdateWindow (hwnd) ;
iDiameter = rand() % (max (1, min (cxClient, cyClient))) ;
hdc = GetDC (hwnd) ;
Ellipse (hdc, (cxClient - iDiameter) / 2,
(cyClient - iDiameter) / 2,
(cxClient + iDiameter) / 2,
(cyClient + iDiameter) / 2) ;
ReleaseDC (hwnd, hdc) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
// --------------------------------------------------------------------------
// Main window to create child windows
// --------------------------------------------------------------------------
LRESULT APIENTRY WndProc ( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND hwndChild[4] ;
static TCHAR * szChildClass[] = { TEXT ("Child1"), TEXT ("Child2"),
TEXT ("Child3"), TEXT ("Child4") } ;
static WNDPROC ChildProc[] = { WndProc1, WndProc2, WndProc3, WndProc4 } ;
HINSTANCE hInstance ;
int i, cxClient, cyClient ;
WNDCLASS wndclass ;
switch (message)
{
case WM_CREATE:
hInstance = (HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE) ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = NULL ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
for (i = 0 ; i < 4 ; i++)
{
wndclass.lpfnWndProc = ChildProc[i] ;
wndclass.lpszClassName = szChildClass[i] ;
RegisterClass (&wndclass) ;
hwndChild[i] = CreateWindow (szChildClass[i], NULL,
WS_CHILDWINDOW | WS_BORDER | WS_VISIBLE,
0, 0, 0, 0,
hwnd, (HMENU) i, hInstance, NULL) ;
}
cyChar = HIWORD (GetDialogBaseUnits ()) ;
SetTimer (hwnd, 1, 10, NULL) ;
return 0 ;
case WM_SIZE:
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
for (i = 0 ; i < 4 ; i++)
MoveWindow (hwndChild[i], (i % 2) * cxClient / 2,
(i > 1) * cyClient / 2,
cxClient / 2, cyClient / 2, TRUE) ;
return 0 ;
case WM_TIMER:
for (i = 0 ; i < 4 ; i++)
SendMessage (hwndChild[i], WM_TIMER, wParam, lParam) ;
return 0 ;
case WM_CHAR:
if (wParam == '/x1B')
DestroyWindow (hwnd) ;
return 0 ;
case WM_DESTROY:
KillTimer (hwnd, 1) ;
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
在这个程序里实际上没有什么我们没见过的东西。主窗口建立四个子窗口,每个子窗口占据显示区域的一个象限。主窗口还设定一个Windows定时器并发送WM_TIMER消息给四个子窗口中的每一个。
通常一个Windows程序应该保留足够的信息以便在WM_PAINT消息处理期间重建其窗口中的内容。MULTI1没有这么做,既然它绘制和清除窗口的速度如此之快,所以我认为那是不必要的。
WndProc2中的质数产生器的效率并不很高,但是有效。如果一个数除了1和它自身以外没有别的因子,那么这个数就是质数。当然,要检查一个数是 否是质数并不要求使用小于被检查数的所有数来除这个数并检查余数,而只需使用所有小于被检查数的平方根的数。平方根计算是发表浮点数的原因,否则,该程序 将是完全依据整数的程序。
MULTI1程序没有什么不好的地方。使用Windows定时器是在Windows的早期(和目前)版本中模拟多任务的一种好方法,然而,定时器的 使用有时限制了程序的速度。如果程序可以在WM_TIMER消息处理中更新它的所有窗口而还有时间剩余下来的话,那就意味着它并没有充分利用我们的机器资 源。
一种可能的解决方案是在单个WM_TIMER消息处理期间进行两次或者更多次的更新,但是到底多少次呢?这不得不依赖于机器的速度,而有很大的变动性。您当然不会想编写一个只能适用于25MHz的386或50MHz的486或100-GHz的Pentium VII上的程序吧。