// --------------------------------------------------------------------------
// 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上的程序吧。