home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / msj / msjv2_3 / tiler / tiler.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-02  |  10.3 KB  |  348 lines

  1. /*
  2. Microsoft Systems Journal
  3. Volume 2; Issue 3; July, 1987
  4.  
  5. Code Listings For:
  6.  
  7.     TILER
  8.     pp. 19-36
  9.  
  10. Author(s): Michael Geary
  11. Title:     Microsoft Windows 2.0: Enhancements Offer Developers More Control
  12.  
  13.  
  14.  
  15.  
  16. Figure 7.
  17. =========
  18.  
  19. Caption: Code Listing for TILER.C
  20.  
  21.  
  22.  
  23. TILER.C
  24. */
  25.  
  26. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\
  27.  *  Tiler.c                                                        *
  28.  *  Windows 2.0 Tiling Utility                                     *
  29.  *  Written by Michael Geary                                       *
  30. \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  31.  
  32. #include <windows.h>
  33.  
  34. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35.  
  36. #define MAXINT      32767
  37.  
  38. /* Menu command definitions */
  39.  
  40. #define CMD_TILECOLS    1
  41. #define CMD_TILEROWS    2
  42.  
  43.  
  44. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  45.  
  46. typedef struct {
  47.     HWND    hWnd;
  48.     RECT    rect;
  49. } WINDOW;
  50.  
  51. WINDOW      Window[4];        /* Window info for each tiled window */
  52. int         nWindows;         /* How many windows we will tile */
  53.  
  54. HANDLE      hInstance;        /* Our instance handle */
  55. int         hWndTiler;        /* hWnd of our icon */
  56. RECT        TileRect;         /* Overall tiling rectangle */
  57.  
  58. char        szClass[] = "Tiler!";         /* Our window class name */
  59. char        szTitle[] = "Tiler";          /* Our window title */
  60. char        szTileCols[] = "&Tile Columns";
  61. char        szTileRows[] = "Tile &Rows";
  62.  
  63. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  64.  
  65.  
  66. /*  Declare full templates for all our functions.  This gives us 
  67.  *  strong type checking on our functions.
  68.  */
  69.  
  70. void                CalcWindowRects( BOOL );
  71. BOOL                Initialize( void );
  72. BOOL                IsTileable( HWND );
  73. long    FAR PASCAL  TilerWndProc( HWND, unsigned, WORD, LONG );
  74. void                TileWindows( BOOL );
  75. int         PASCAL  WinMain( HANDLE, HANDLE, LPSTR, int );
  76.  
  77. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  78.  
  79.  
  80. /*  Calculate window rectangles for the four topmost tileable windows
  81.  *  and set up the Window array for them.  This is a simple-minded
  82.  *  tiling algorithm that simply divides the tiling area into equal
  83.  *  rows and columns.
  84.  */
  85.  
  86. void CalcWindowRects( bColumns )
  87.     BOOL        bColumns;
  88. {
  89.     HWND        hWnd;
  90.     int         n;
  91.  
  92.     n = 0;
  93.     for(
  94.         hWnd = GetWindow( hWndTiler, GW_HWNDFIRST );
  95.         hWnd;
  96.         hWnd = GetWindow( hWnd, GW_HWNDNEXT )
  97.     ) {
  98.         if( ! IsTileable( hWnd ) )  continue;
  99.  
  100.         Window[n].hWnd = hWnd;
  101.         CopyRect( &Window[n].rect, &TileRect );
  102.  
  103.         switch( n ) {
  104.             case 0:
  105.                 break;
  106.             case 1:
  107.                 if( bColumns ) {
  108.                     Window[0].rect.right = TileRect.right / 2;
  109.                     Window[1].rect.left = Window[0].rect.right - 1;
  110.                 } else {
  111.                     Window[0].rect.bottom = TileRect.bottom / 2;
  112.                     Window[1].rect.top = Window[0].rect.bottom - 1;
  113.                 }
  114.                 break;
  115.             case 2:
  116.                 if( bColumns ) {
  117.                     Window[2].rect.left = Window[1].rect.left;
  118.                     Window[1].rect.bottom = TileRect.bottom / 2;
  119.                     Window[2].rect.top = Window[1].rect.bottom - 1;
  120.                 } else {
  121.                     Window[2].rect.top = Window[1].rect.top;
  122.                     Window[1].rect.right = TileRect.right / 2;
  123.                     Window[2].rect.left = Window[1].rect.right - 1;
  124.                 }
  125.                 break;
  126.             case 3:
  127.                 if( bColumns ) {
  128.                     Window[3].rect.right = Window[0].rect.right;
  129.                     Window[0].rect.bottom = TileRect.bottom / 2;
  130.                     Window[3].rect.top = Window[0].rect.bottom - 1;
  131.                 } else {
  132.                     Window[3].rect.bottom = Window[0].rect.bottom;
  133.                     Window[0].rect.right = TileRect.right / 2;
  134.                     Window[3].rect.left = Window[0].rect.right - 1;
  135.                 }
  136.                 break;
  137.         }
  138.         if( ++n == 4 )  break;
  139.     }
  140.     nWindows = n;
  141. }
  142.  
  143. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  144.  
  145.  
  146. /*  Initialize TILER.  Assumes a single instance.
  147.  *  Returns TRUE if initialization succeeded, FALSE if failed.
  148.  */
  149.  
  150. BOOL Initialize()
  151. {
  152.     WNDCLASS    Class;        /* Class structure for RegisterClass */
  153.     HMENU       hMenu;        /* Menu handle of system menu */
  154.  
  155.     /* Register our window class */
  156.     Class.style          = 0;
  157.     Class.cbClsExtra     = 0;
  158.     Class.cbWndExtra     = 0;
  159.     Class.lpfnWndProc    = TilerWndProc;
  160.     Class.hInstance      = hInstance;
  161.     Class.hIcon          = LoadIcon( hInstance, szClass );
  162.     Class.hCursor        = LoadCursor( NULL, IDC_ARROW );
  163.     Class.hbrBackground  = COLOR_WINDOW + 1;
  164.     Class.lpszMenuName   = NULL;
  165.     Class.lpszClassName  = szClass;
  166.  
  167.     if( ! RegisterClass( &Class ) )  return FALSE;
  168.  
  169.     /* Create our window but don't iconize it yet */
  170.     hWndTiler = CreateWindow(
  171.         szClass, szTitle,
  172.         WS_OVERLAPPED | WS_SYSMENU,
  173.         CW_USEDEFAULT, 0,
  174.         CW_USEDEFAULT, 0,
  175.         NULL, NULL, hInstance, NULL
  176.     );
  177.     if( ! hWndTiler )  return FALSE;
  178.  
  179.     /* Since we took the default size, the bottom of our window is
  180.      * the base Y coordinate for tiling */
  181.     GetWindowRect( hWndTiler, &TileRect );
  182.     TileRect.top = TileRect.left = -1;
  183.     TileRect.right = GetSystemMetrics( SM_CXSCREEN ) + 1;
  184.  
  185.     /* Add our menu items to the System (Control) menu */
  186.     hMenu = GetSystemMenu( hWndTiler, FALSE);
  187.     ChangeMenu( hMenu, 0, NULL, MAXINT, MF_APPEND | MF_SEPARATOR );
  188.     ChangeMenu( hMenu, 0, szTileCols, CMD_TILECOLS, 
  189.                 MF_APPEND | MF_STRING );
  190.     ChangeMenu( hMenu, 0, szTileRows, CMD_TILEROWS, 
  191.                 MF_APPEND | MF_STRING );
  192.  
  193.     /* Now display our window as an icon */
  194.     ShowWindow( hWndTiler, SW_SHOWMINIMIZED );
  195.  
  196.     return TRUE;
  197. }
  198.  
  199. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  200.  
  201.  
  202. /*  Tells whether a window can be tiled, returns TRUE if so.
  203.  *  We will tile only top level, resizable windows that are not
  204.  *  minimized and not maximized.
  205.  */
  206.  
  207. BOOL IsTileable( hWnd )
  208.     HWND        hWnd;
  209. {
  210.     DWORD       dwStyle;
  211.  
  212.     dwStyle = GetWindowLong( hWnd, GWL_STYLE );
  213.     return(
  214.         ! ( dwStyle & ( WS_POPUP | WS_MINIMIZE | WS_MAXIMIZE ) )  &&
  215.           ( dwStyle & WS_SIZEBOX )  &&
  216.           ( dwStyle & WS_VISIBLE )
  217.     );
  218. }
  219.  
  220. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  221.  
  222.  
  223. /*  Tiler's window function.
  224.  */
  225.  
  226. long FAR PASCAL TilerWndProc( hWnd, wMsg, wParam, lParam )
  227.     HWND        hWnd;            /* Window handle */
  228.     unsigned    wMsg;            /* Message number */
  229.     WORD        wParam;          /* Word parameter for the message */
  230.     LONG        lParam;          /* Long parameter for the message */
  231. {
  232.     RECT        rect;            /* A rectangle */
  233.  
  234.     switch( wMsg ) {
  235.  
  236.     /* Destroy-window message - time to quit the application */
  237.         case WM_DESTROY:
  238.             PostQuitMessage( 0 );
  239.             return 0L;
  240.  
  241.     /* Query open icon message - don't allow icon to be opened! */
  242.         case WM_QUERYOPEN:
  243.             return 0L;
  244.  
  245.     /* System menu command message - process the command if ours */
  246.         case WM_SYSCOMMAND:
  247.             switch( wParam ) {
  248.                 case CMD_TILECOLS:
  249.                     TileWindows( TRUE );
  250.                     return 0L;
  251.                 case CMD_TILEROWS:
  252.                     TileWindows( FALSE );
  253.                     return 0L;
  254.                 default:
  255.                     break;
  256.             }
  257.             break;
  258.  
  259.     /* For all other messages, we pass them on to DefWindowProc */
  260.         default:
  261.             break;
  262.     }
  263.     return DefWindowProc( hWnd, wMsg, wParam, lParam );
  264. }
  265.  
  266. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  267.  
  268. /*  This function actually tiles the windows.  First, it calls
  269.  *  CalcWindowRects to determine the window positions.  Then, it 
  270.  *  loops through the windows and moves them into place.
  271.  */
  272.  
  273. void TileWindows( bColumns )
  274.     BOOL        bColumns;     /* TRUE = tile columns; FALSE = rows */
  275. {
  276.     int         n;
  277.     HWND        hWnd = NULL;
  278.  
  279.     CalcWindowRects( bColumns );  /* Assign window rectangles */
  280.  
  281.     if( nWindows == 0 ) {
  282.         MessageBox(
  283.             hWndTiler,
  284.             "There are no windows that can be tiled.",
  285.             szTitle,
  286.             MB_OK | MB_ICONEXCLAMATION
  287.         );
  288.         return;
  289.     }
  290.  
  291.     /* Move, size, and reorder windows */
  292.     for( n = 0;  n < nWindows;  ++n ) { 
  293.         SetWindowPos(
  294.             Window[n].hWnd,
  295.             hWnd,
  296.             Window[n].rect.left,
  297.             Window[n].rect.top,
  298.             Window[n].rect.right  - Window[n].rect.left,
  299.             Window[n].rect.bottom - Window[n].rect.top,
  300.             SWP_NOACTIVATE
  301.         );
  302.         hWnd = Window[n].hWnd;
  303.         if( GetClassWord( hWnd, GCW_STYLE ) & 
  304.                         ( CS_HREDRAW | CS_VREDRAW ) )
  305.             /* Make sure it's redrawn */
  306.             InvalidateRect( hWnd, NULL, TRUE );
  307.     }
  308. }
  309.  
  310. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  311.  
  312. /*  Application main program. */
  313.  
  314. int PASCAL WinMain( hInst, hPrevInst, lpszCmdLine, nCmdShow )
  315.  
  316.     /* Our instance handle */
  317.     HANDLE      hInst; 
  318.     /* Previous instance of this application*/
  319.     HANDLE      hPrevInst; 
  320.     /* Pointer to any command line params*/
  321.     LPSTR       lpszCmdLine;
  322.     /* Parameter to use for first ShowWindow */
  323.     int         nCmdShow; 
  324. {
  325.     MSG         msg;                /* Message structure */
  326.  
  327.     /* Allow only a single instance */
  328.     if( hPrevInst ) {
  329.         MessageBeep( 0 );
  330.         return 0;
  331.     }
  332.  
  333.     /* Save our instance handle in static variable */
  334.     hInstance = hInst;
  335.  
  336.     /* Initialize application, quit if any errors */
  337.     if( ! Initialize() )  return FALSE;
  338.  
  339.     /* Main message processing loop */
  340.     while( GetMessage( &msg, NULL, 0, 0 ) ) {
  341.         DispatchMessage( &msg );
  342.     }
  343.  
  344.     return msg.wParam;
  345. }
  346.  
  347. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  348.