Initialization Procedures

The initialization procedures register two window classes, one for the main overlapping window and one for the child windows where the threads draw. They also create a timer. At five-second intervals, the list box updates the information about each thread. The CreateWindows function creates and positions all the windows, including the list box that shows information about each thread. The four threads are created during the WM_CREATE message handler.

/*—————————————————————————————————————————————————————————————————————
   WIN MAIN
      Calls initializing procedures and runs the message loop
—————————————————————————————————————————————————————————————————————*/
int WINAPI WinMain(  HINSTANCE hinstThis, HINSTANCE hinstPrev,
                    LPSTR lpszCmdLine,   int iCmdShow  )
{
   MSG msg;
   hInst = hinstThis;          // store in global variable
   if( ! InitializeApp( ) )
   {
      // if the application was not initialized, exit here
      return( 0 );
   }
   ShowWindow( hwndParent, iCmdShow );
   UpdateWindow( hwndParent );
         // receive and forward messages from our queue 
   while( GetMessage( &msg, NULL, 0, 0 ) )
   {
      TranslateMessage( &msg );
      DispatchMessage( &msg );
   }
   return( msg.wParam );
}

NOTE

Note the absence of a PeekMessage loop in WinMain. That’s a clear sign that you have entered the world of preemptive multitasking. (In preemptive multitasking, the system interrupts executing threads to permit other threads access to the CPU; in permissive multitasking the system waits for a thread to relinquish control of the CPU.) The threads can draw continuously without monopolizing the processor. Other programs can still run at the same time.

In addition to registering the application class and following the usual setup procedures, the InitializeApp procedure sets the thread priority and starts each thread in a suspended state.

/*——————————————————————————————————————————————————————————————————————————
   INITIALIZE APP
      Register two window classes and then create the windows
——————————————————————————————————————————————————————————————————————————*/
BOOL InitializeApp ( void )
{
   ...
      // mark the initial state of each thread as SUSPENDED
      // that is how they will be created
   for( iCount = 0; iCount < 4; iCount++ )
   {
      iState[iCount] = SUSPENDED;
   }
      // make the primary thread more important to facilitate user i/o 
   SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL );
      // create all the windows 
   return( CreateWindows( ) );
}

The call to SetThreadPriority increases the priority of the primary thread. If all the secondary threads were busy working at the same priority as the main thread, the menus would respond sluggishly. You can test this yourself by raising the priority of the secondary threads as the program runs.

The CreateWindows function  creates not only the main window but also a list box and a series of child windows for the threads.

/*—————————————————————————————————————————————————————————————————————
   CREATE WINDOWS
      Create the parent window, the list box window, and the four       child windows.
—————————————————————————————————————————————————————————————————————*/
BOOL CreateWindows ( void )
{
   char   szAppName[MAX_BUFFER];
   char   szTitle[MAX_BUFFER];
   char   szThread[MAX_BUFFER];
   HMENU  hMenu;
   int    iCount;
      // load the relevant strings 
   LoadString( hInst, IDS_APPNAME, szAppName,  sizeof(szAppName));
   LoadString( hInst, IDS_TITLE,   szTitle,    sizeof(szTitle));
   LoadString( hInst, IDS_THREAD,  szThread,   sizeof(szThread));
      // create the parent window
   hMenu = LoadMenu( hInst, MAKEINTRESOURCE(MENU_MAIN) );
   hwndParent = CreateWindow( szAppName, szTitle,
                              WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
                              CW_USEDEFAULT, CW_USEDEFAULT,
                              CW_USEDEFAULT, CW_USEDEFAULT,
                              NULL, hMenu, hInst, NULL );
   if( ! hwndParent )
   {
      return( FALSE );
   }
      // create the list box
   hwndList = CreateWindow( “LISTBOX”, NULL,
                            WS_BORDER | WS_CHILD | WS_VISIBLE |
                            LBS_STANDARD | LBS_NOINTEGRALHEIGHT,
                            0, 0, 0, 0, hwndParent, (HMENU)1,
                            hInst, NULL );
   if( ! hwndList )
   {
      return( FALSE );
   }
      // create the four child windows
   for( iCount = 0; iCount < 4; iCount++ )
   {
      hwndChild[iCount] = CreateWindow( “ThreadClass”, NULL,
                                        WS_BORDER | WS_CHILD |
                                        WS_VISIBLE | WS_CLIPCHILDREN,
                                        0, 0, 0, 0, hwndParent, NULL,
                                        hInst, NULL );
      if( ! hwndChild ) return( FALSE );
   }
   return( TRUE );
}

© 1998 SYBEX Inc. All rights reserved.