home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / windows / tiler.zip / TILER.C < prev    next >
Text File  |  1987-09-05  |  13KB  |  427 lines

  1. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *\
  2.  *  Tiler.c                                     *
  3.  *  Windows 2.0 Tiling Utility                             *
  4.  *  Written by Michael Geary                             *
  5. \* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  6.  
  7. #include <windows.h>
  8. #include "Tiler.h"
  9.  
  10. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  11.  
  12. #define MAXINT        32767
  13.  
  14. /* Menu command definitions */
  15.  
  16. #define CMD_TILECOLS    1
  17. #define CMD_TILEROWS    2
  18. #define CMD_MARGINS    3
  19. #define CMD_ABOUT    4
  20.  
  21. /* Code macros */
  22.  
  23. #define ROUNDUP( n )  ( ( (n) | 7 ) + 1 )
  24.  
  25. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  26.  
  27. HANDLE        hInstance;            /* Our instance handle */
  28. int        hWndTiler;            /* hWnd of our icon */
  29.  
  30. typedef struct {
  31.     HWND    hWnd;
  32.     RECT    rect;
  33. } WINDOW;
  34.  
  35. WINDOW        Window[4];            /* Window info for each tiled window */
  36. int        nWindows;            /* How many windows we will tile */
  37.  
  38. RECT        rcTile1;            /* Top-left tiling rectangle */
  39. RECT        rcTile2;            /* Bottom-right tiling rectangle */
  40. BOOL        bMargins = TRUE;        /* Provide margins? */
  41.  
  42. char        szClass[] = "Tiler!";         /* Our window class name */
  43. char        szTitle[] = "Tiler";          /* Our window title */
  44. char        szTileCols[] = "&Tile Columns";
  45. char        szTileRows[] = "Tile &Rows";
  46. char        szMargins[]  = "M&argins";
  47. char        szAbout[]     = "A&bout Tiler...";
  48.  
  49. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  50.  
  51. /*  Declare full templates for all our functions.  This gives us strong type
  52.  *  checking on our functions.
  53.  */
  54.  
  55. BOOL    FAR PASCAL  AboutBox( HWND, unsigned, WORD, LONG );
  56. void            CalcTileRects( void );
  57. void            CalcWindowRects( BOOL );
  58. BOOL            Initialize( void );
  59. BOOL            IsTileable( HWND );
  60. long    FAR PASCAL  TilerWndProc( HWND, unsigned, WORD, LONG );
  61. void            TileWindows( BOOL );
  62. int        PASCAL  WinMain( HANDLE, HANDLE, LPSTR, int );
  63.  
  64. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  65.  
  66. /*  Dialog function for the About box.
  67.  *  Since this is a simple box with only one button, WM_COMMAND is assumed
  68.  *  to be a click on that button (the command number is not checked).
  69.  */
  70.  
  71. BOOL FAR AboutBox( hDlg, wMsg, wParam, lParam )
  72.     HWND    hDlg;            /* Window handle */
  73.     unsigned    wMsg;            /* Message number */
  74.     WORD    wParam;         /* Word parameter for the message */
  75.     LONG    lParam;         /* Long parameter for the message */
  76. {
  77.     switch( wMsg ) {
  78.     case WM_COMMAND:
  79.         EndDialog( hDlg, TRUE );
  80.         return TRUE;
  81.     }
  82.     return FALSE;
  83. }
  84.  
  85. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  86.  
  87. /*  Calculate the outer tiling rectangle and center point according to
  88.  *  the current setting of bMargins.  rcTile2.bottom is set up during
  89.  *  initialization, so we leave it alone here.
  90.  */
  91.  
  92. void CalcTileRects()
  93. {
  94.     POINT    ptFrameSize;        /* X and Y window frame sizes */
  95.     POINT    ptFrameBytes;        /* ditto, rounded up to byte value */
  96.     POINT    ptMargin;        /* X and Y margin sizes */
  97.     int     nScreenWidth;        /* Screen width in pixels */
  98.  
  99.     ptFrameSize.x = GetSystemMetrics( SM_CXFRAME );
  100.     ptFrameBytes.x = ROUNDUP( ptFrameSize.x );
  101.     ptMargin.x = ptFrameBytes.x - ptFrameSize.x;
  102.  
  103.     ptFrameSize.y = GetSystemMetrics( SM_CYFRAME );
  104.     ptFrameBytes.y = ROUNDUP( ptFrameSize.y );
  105.     ptMargin.y = ptFrameBytes.y - ptFrameSize.y;
  106.  
  107.     nScreenWidth = GetSystemMetrics( SM_CXSCREEN );
  108.  
  109.     if( bMargins ) {
  110.     rcTile1.left   = ptMargin.x;
  111.     rcTile1.top    = ptMargin.y;
  112.     rcTile2.right  = nScreenWidth - ptMargin.x;
  113.     rcTile2.left   =
  114.         ROUNDUP( ( ( rcTile2.right - rcTile1.left ) >> 1 ) + ptMargin.x )
  115.         - ptFrameSize.x;
  116.     rcTile1.right  = rcTile2.left - ptMargin.x;
  117.     rcTile2.top    =
  118.         ( rcTile2.bottom - rcTile1.top - ptMargin.y ) >> 1;
  119.     rcTile1.bottom = rcTile2.top - ptMargin.y;
  120.     } else {
  121.     rcTile1.left   = -ptFrameSize.x;
  122.     rcTile1.top    = -ptFrameSize.y;
  123.     rcTile2.right  = nScreenWidth + ptFrameSize.x;
  124.     rcTile2.left   =
  125.         ROUNDUP( ( rcTile2.right - rcTile1.left + ptFrameSize.x ) >> 1 )
  126.         - ptFrameSize.x;
  127.     rcTile1.right  = rcTile2.left + ptFrameSize.x;
  128.     rcTile2.top    =
  129.         ( rcTile2.bottom - rcTile1.top + ptFrameSize.y ) >> 1;
  130.     rcTile1.bottom = rcTile2.top + ptFrameSize.y;
  131.     }
  132. }
  133.  
  134. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  135.  
  136. /*  Calculate window rectangles for the four topmost tileable windows
  137.  *  and set up the Window array for them.  This is a very simpleminded
  138.  *  tiling algorithm that simply divides the tiling area into equal
  139.  *  rows and columns.
  140.  */
  141.  
  142. void CalcWindowRects( bColumns )
  143.     BOOL    bColumns;
  144. {
  145.     HWND    hWnd;
  146.     int     n;
  147.  
  148.     n = 0;
  149.     for(
  150.     hWnd = GetWindow( hWndTiler, GW_HWNDFIRST );
  151.     hWnd;
  152.     hWnd = GetWindow( hWnd, GW_HWNDNEXT )
  153.     ) {
  154.     if( ! IsTileable( hWnd ) )
  155.         continue;
  156.  
  157.     Window[n].hWnd = hWnd;
  158.  
  159.     /* Assume full screen to start with */
  160.     Window[n].rect.left   = rcTile1.left;
  161.     Window[n].rect.top    = rcTile1.top;
  162.     Window[n].rect.right  = rcTile2.right;
  163.     Window[n].rect.bottom = rcTile2.bottom;;
  164.  
  165.     switch( n ) {
  166.         case 0:
  167.         break;
  168.         case 1:
  169.         if( bColumns ) {
  170.             Window[0].rect.right  = rcTile1.right;
  171.             Window[1].rect.left   = rcTile2.left;
  172.         } else {
  173.             Window[0].rect.bottom = rcTile1.bottom;
  174.             Window[1].rect.top      = rcTile2.top;
  175.         }
  176.         break;
  177.         case 2:
  178.         if( bColumns ) {
  179.             Window[2].rect.left   = rcTile2.left;
  180.             Window[1].rect.bottom = rcTile1.bottom;
  181.             Window[2].rect.top      = rcTile2.top;
  182.         } else {
  183.             Window[2].rect.top      = rcTile2.top;
  184.             Window[1].rect.right  = rcTile1.right;
  185.             Window[2].rect.left   = rcTile2.left;
  186.         }
  187.         break;
  188.         case 3:
  189.         if( bColumns ) {
  190.             Window[3].rect.right  = rcTile1.right;
  191.             Window[0].rect.bottom = rcTile1.bottom;
  192.             Window[3].rect.top      = rcTile2.top;
  193.         } else {
  194.             Window[3].rect.bottom = rcTile1.bottom;
  195.             Window[0].rect.right  = rcTile1.right;
  196.             Window[3].rect.left   = rcTile2.left;
  197.         }
  198.         break;
  199.     }
  200.     if( ++n == 4 )
  201.         break;
  202.     }
  203.     nWindows = n;
  204. }
  205.  
  206. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  207.  
  208. /*  Initialize TILER.  Assumes a single instance.
  209.  *  Returns TRUE if initialization succeeded, FALSE if failed.
  210.  */
  211.  
  212. BOOL Initialize()
  213. {
  214.     WNDCLASS    Class;            /* Class structure for RegisterClass */
  215.     HMENU    hMenu;            /* Menu handle of system menu */
  216.  
  217.     /* Register our window class */
  218.     Class.style      = 0;
  219.     Class.cbClsExtra     = 0;
  220.     Class.cbWndExtra     = 0;
  221.     Class.lpfnWndProc     = TilerWndProc;
  222.     Class.hInstance     = hInstance;
  223.     Class.hIcon      = LoadIcon( hInstance, szClass );
  224.     Class.hCursor     = LoadCursor( NULL, IDC_ARROW );
  225.     Class.hbrBackground  = COLOR_WINDOW + 1;
  226.     Class.lpszMenuName     = NULL;
  227.     Class.lpszClassName  = szClass;
  228.  
  229.     if( ! RegisterClass( &Class ) )
  230.     return FALSE;
  231.  
  232.     /* Create our window but don't iconize it yet */
  233.     hWndTiler = CreateWindow(
  234.     szClass, szTitle,
  235.     WS_OVERLAPPED | WS_SYSMENU,
  236.     CW_USEDEFAULT, 0,
  237.     CW_USEDEFAULT, 0,
  238.     NULL, NULL, hInstance, NULL
  239.     );
  240.     if( ! hWndTiler )
  241.     return FALSE;
  242.  
  243.     /* Since we took the default size, the bottom of our window is the
  244.      * base Y coordinate for tiling */
  245.     GetWindowRect( hWndTiler, &rcTile2 );
  246.  
  247.     /* Add our menu items to the System (Control) menu, at the top of
  248.      * the menu, so "Tile Columns" becomes the default choice */
  249.     hMenu = GetSystemMenu( hWndTiler, FALSE );
  250.     ChangeMenu( hMenu, 0, NULL,       MAXINT,        MF_APPEND | MF_SEPARATOR );
  251.     ChangeMenu( hMenu, 0, szTileCols, CMD_TILECOLS, MF_APPEND             );
  252.     ChangeMenu( hMenu, 0, szTileRows, CMD_TILEROWS, MF_APPEND             );
  253.     ChangeMenu( hMenu, 0, NULL,       MAXINT,        MF_APPEND | MF_SEPARATOR );
  254.     ChangeMenu( hMenu, 0, szMargins,  CMD_MARGINS,  MF_APPEND | MF_CHECKED   );
  255.     ChangeMenu( hMenu, 0, NULL,       MAXINT,        MF_APPEND | MF_SEPARATOR );
  256.     ChangeMenu( hMenu, 0, szAbout,    CMD_ABOUT,    MF_APPEND             );
  257.  
  258.     /* Now display our window as an icon */
  259.     ShowWindow( hWndTiler, SW_SHOWMINIMIZED );
  260.  
  261.     return TRUE;
  262. }
  263.  
  264. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  265.  
  266. /*  Tells whether a window can be tiled, returns TRUE if so.
  267.  *  We will tile only top level, resizable windows that are not
  268.  *  minimized and not maximized.
  269.  */
  270.  
  271. BOOL IsTileable( hWnd )
  272.     HWND    hWnd;
  273. {
  274.     DWORD    dwStyle;
  275.  
  276.     dwStyle = GetWindowLong( hWnd, GWL_STYLE );
  277.     return(
  278.     ! ( dwStyle & ( WS_POPUP | WS_MINIMIZE | WS_MAXIMIZE ) )  &&
  279.       ( dwStyle & WS_SIZEBOX )  &&
  280.       ( dwStyle & WS_VISIBLE )
  281.     );
  282. }
  283.  
  284. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  285.  
  286. /*  Tiler's window function.
  287.  */
  288.  
  289. long FAR PASCAL TilerWndProc( hWnd, wMsg, wParam, lParam )
  290.     HWND    hWnd;            /* Window handle */
  291.     unsigned    wMsg;            /* Message number */
  292.     WORD    wParam;         /* Word parameter for the message */
  293.     LONG    lParam;         /* Long parameter for the message */
  294. {
  295.     FARPROC    lpProc;         /* ProcInstance for AboutBox */
  296.  
  297.     switch( wMsg ) {
  298.  
  299.     /* Destroy-window message - time to quit the application */
  300.     case WM_DESTROY:
  301.         PostQuitMessage( 0 );
  302.         return 0L;
  303.  
  304.     /* Query open icon message - don't allow icon to be opened! */
  305.     case WM_QUERYOPEN:
  306.         return 0L;
  307.  
  308.     /* System menu command message - process the command if ours */
  309.     case WM_SYSCOMMAND:
  310.         switch( wParam ) {
  311.  
  312.         case CMD_MARGINS:
  313.             bMargins = ! bMargins;
  314.             CheckMenuItem(
  315.             GetSystemMenu( hWnd, FALSE ),
  316.             wParam,
  317.             bMargins ? MF_CHECKED : MF_UNCHECKED
  318.             );
  319.             return 0L;
  320.  
  321.         case CMD_TILECOLS:
  322.             TileWindows( TRUE );
  323.             return 0L;
  324.  
  325.         case CMD_TILEROWS:
  326.             TileWindows( FALSE );
  327.             return 0L;
  328.  
  329.         case CMD_ABOUT:
  330.             lpProc = MakeProcInstance( (FARPROC)AboutBox, hInstance );
  331.             if( ! lpProc )
  332.             return 0L;
  333.             DialogBox(
  334.             hInstance,
  335.             MAKEINTRESOURCE(ABOUTBOX),
  336.             hWnd,
  337.             lpProc
  338.             );
  339.             FreeProcInstance( lpProc );
  340.             return 0L;
  341.  
  342.         }
  343.         break;
  344.     }
  345.  
  346.     /* For all other messages, we pass them on to DefWindowProc */
  347.     return DefWindowProc( hWnd, wMsg, wParam, lParam );
  348. }
  349.  
  350. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  351.  
  352. /*  This function actually tiles the windows.  First, it calculates the
  353.  *  tiling rectangles for the windows.    Then, it loops through the windows
  354.  *  and moves them into place.
  355.  */
  356.  
  357. void TileWindows( bColumns )
  358.     BOOL    bColumns;        /* TRUE = tile columns; FALSE = rows */
  359. {
  360.     int     n;
  361.     HWND    hWnd = NULL;
  362.  
  363.     CalcTileRects();  /* Calculate tiling rectangle for current settings */
  364.     CalcWindowRects( bColumns );  /* Assign window rectangles */
  365.  
  366.     if( nWindows == 0 ) {
  367.     MessageBox(
  368.         hWndTiler,
  369.         "There are no windows that can be tiled.",
  370.         szTitle,
  371.         MB_OK | MB_ICONEXCLAMATION
  372.     );
  373.     return;
  374.     }
  375.  
  376.     for( n = 0;  n < nWindows;    ++n ) {  /* Move, size, and reorder windows */
  377.     SetWindowPos(
  378.         Window[n].hWnd,
  379.         hWnd,
  380.         Window[n].rect.left,
  381.         Window[n].rect.top,
  382.         Window[n].rect.right  - Window[n].rect.left,
  383.         Window[n].rect.bottom - Window[n].rect.top,
  384.         SWP_NOACTIVATE
  385.     );
  386.     }
  387.  
  388.     SetActiveWindow( Window[0].hWnd );    /* Activate the first window */
  389. }
  390.  
  391. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  392.  
  393. /*  Application main program.
  394.  */
  395.  
  396. int PASCAL WinMain( hInst, hPrevInst, lpszCmdLine, nCmdShow )
  397.     HANDLE    hInst;            /* Our instance handle */
  398.     HANDLE    hPrevInst;        /* Previous instance of this application */
  399.     LPSTR    lpszCmdLine;        /* Pointer to any command line params */
  400.     int     nCmdShow;        /* Parameter to use for first ShowWindow */
  401. {
  402.     MSG     msg;            /* Message structure */
  403.  
  404.     /* Allow only a single instance */
  405.     if( hPrevInst ) {
  406.     MessageBeep( 0 );
  407.     return 0;
  408.     }
  409.  
  410.     /* Save our instance handle in static variable */
  411.     hInstance = hInst;
  412.  
  413.     /* Initialize application, quit if any errors */
  414.     if( ! Initialize() )
  415.     return FALSE;
  416.  
  417.     /* Main message processing loop */
  418.     while( GetMessage( &msg, NULL, 0, 0 ) ) {
  419.     TranslateMessage( &msg );
  420.     DispatchMessage( &msg );
  421.     }
  422.  
  423.     return msg.wParam;
  424. }
  425.  
  426. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  427.