home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / pcmagazi / 1992 / 16 / totop.c < prev    next >
C/C++ Source or Header  |  1992-09-28  |  10KB  |  297 lines

  1. #include<windows.h>
  2. #include<string.h>
  3.  
  4. #define IDM_ABOUT  0xE010
  5. #define IDM_HELP   0xE020
  6. #define IDM_TOP    0xE030
  7. #define IDM_BOTTOM 0xE040
  8. #define DO_TOP     1
  9. #define DO_BOTTOM  2
  10.  
  11. HMENU hmSystemMenu=NULL;
  12. LPSTR szAppName="ToTop";
  13. HANDLE hInst;
  14. HWND hWndMain;
  15. int nDoingTopBottomAction=0,nGotLButtonDown,nSuccess;
  16. int nDestroyOkCursor=0,nDestroyNotOkCursor=0,nShowingOkCursor;
  17. HCURSOR hcOldCursor=NULL,hcOkCursor=NULL,hcNotOkCursor=NULL;
  18.  
  19. int PASCAL WinMain(HANDLE hInstance,HANDLE hPrevInstance,
  20.     LPSTR lpszCmdLine,int nCmdShow);
  21. LONG FAR PASCAL WndProc(HWND, WORD, WORD, LONG);
  22. void DoTopBottomAction(int nTopOrBottom);
  23. void StopDoingTopBottomAction(void);
  24. void TopBottomWindowAtPoint(long lParam);
  25. HWND IsDoable(long lParam);
  26.  
  27. int PASCAL WinMain(HANDLE hInstance,HANDLE hPrevInstance,
  28. LPSTR lpszCmdLine,int nCmdShow){
  29.     MSG msg;
  30.     hInst=hInstance;
  31.     if(hPrevInstance){                  /* one instance */
  32.         MessageBox(NULL,"Cannot start multiple\n"
  33.         "instances of ToTop",NULL,MB_ICONSTOP);
  34.         return 1;
  35.     }
  36.     if(0x30a>((LOBYTE(LOWORD(GetVersion()))<<8)|    /* win 3.1? */
  37.     (HIBYTE(LOWORD(GetVersion()))))){
  38.         MessageBox(NULL,"ToTop requires\n"
  39.         "Windows 3.1 or better",NULL,MB_ICONSTOP);
  40.         return 1;
  41.     }
  42.     if(!GetSystemMetrics(SM_MOUSEPRESENT)){   /* mouse? */
  43.         MessageBox(NULL,"ToTop requires\na mouse",NULL,MB_ICONSTOP);
  44.         return 1;
  45.     }
  46.     {                                   /* make window class */
  47.         WNDCLASS wndclass;
  48.         memset(&wndclass, 0x00, sizeof(WNDCLASS));
  49.         wndclass.style=CS_DBLCLKS;
  50.         wndclass.lpfnWndProc=WndProc;
  51.         wndclass.cbClsExtra=0;
  52.         wndclass.cbWndExtra=0;
  53.         wndclass.hInstance=hInst;
  54.         wndclass.hIcon=LoadIcon(hInst,"ToTopIcon");
  55.         wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
  56.         wndclass.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
  57.         wndclass.lpszMenuName=szAppName;
  58.         wndclass.lpszClassName=szAppName;
  59.         if(!RegisterClass(&wndclass)){
  60.             MessageBox(NULL,"Could not register class",
  61.             NULL,MB_ICONEXCLAMATION);
  62.             return 1;
  63.         }
  64.     }
  65.     hWndMain=CreateWindowEx(WS_EX_TOPMOST,szAppName,szAppName,
  66.     WS_CAPTION|WS_SYSMENU|WS_ICONIC|WS_CLIPCHILDREN|WS_OVERLAPPED,
  67.     CW_USEDEFAULT,0,CW_USEDEFAULT,0,NULL,NULL,hInst,NULL);
  68.     if(hWndMain==NULL){                 /* couldn't create */
  69.         UnregisterClass(szAppName,hInst);
  70.         MessageBox(NULL,"Could not create window",
  71.         NULL,MB_ICONEXCLAMATION);
  72.         return 1;
  73.     }
  74.     hmSystemMenu=GetSystemMenu(hWndMain,FALSE);
  75.     AppendMenu(hmSystemMenu,MF_SEPARATOR,0,(LPSTR)NULL);
  76.     AppendMenu(hmSystemMenu,MF_STRING,IDM_HELP,"&Help...");
  77.     AppendMenu(hmSystemMenu,MF_STRING,IDM_ABOUT,"&About...");
  78.     AppendMenu(hmSystemMenu,MF_SEPARATOR,0,(LPSTR)NULL);
  79.     AppendMenu(hmSystemMenu,MF_STRING,IDM_TOP,"&Top");
  80.     AppendMenu(hmSystemMenu,MF_STRING,IDM_BOTTOM,"&Bottom");
  81.                                         /* done modifying menu */
  82.     ShowWindow(hWndMain, SW_SHOWMINIMIZED);
  83.     while(GetMessage(&msg,NULL,0,0)){
  84.         TranslateMessage(&msg);
  85.         DispatchMessage(&msg);
  86.     }
  87.     UnregisterClass(szAppName,hInst);
  88.     return msg.wParam;
  89. }
  90. LONG FAR PASCAL WndProc(HWND hWnd,WORD Message,
  91. WORD wParam,LONG lParam){
  92.     HWND hwndTemp;
  93.     switch(Message){
  94.     case WM_SYSCOMMAND:
  95.         switch(wParam&0xFFF0){
  96.         case IDM_TOP:
  97.             DoTopBottomAction(DO_TOP);
  98.             break;
  99.         case IDM_BOTTOM:
  100.             DoTopBottomAction(DO_BOTTOM);
  101.             break;
  102.         case IDM_HELP:
  103.             MessageBox(hWnd,
  104.             "ToTop can 'float' or 'sink'\n"
  105.             "any application\n"
  106.             "running under Windows 3.1\n\n"
  107.             "Choose Top or Bottom,\n"
  108.             "then click the left mouse\n"
  109.             "button on any window\n\n"
  110.             "Use right mouse button to cancel",
  111.             "Using ToTop",MB_ICONINFORMATION);
  112.             break;
  113.         case IDM_ABOUT:
  114.             MessageBox(hWnd,
  115.             "ToTop 1.0\n"
  116.             "Copyright ⌐ 1992 John Deurbrouck\n\n"
  117.             "First published in PC Magazine\n"
  118.             "September 29, 1992",
  119.             "About ToTop",MB_ICONINFORMATION);
  120.             break;
  121.         case SC_MAXIMIZE:
  122.         case SC_RESTORE:
  123.         case SC_SIZE:
  124.             break;
  125.         default:
  126.             return DefWindowProc(hWnd,Message,wParam,lParam);
  127.         }
  128.         break;
  129.     case WM_SIZE:
  130.         switch(wParam){
  131.         case SIZE_MAXIMIZED:
  132.         case SIZE_RESTORED:
  133.             break;
  134.         default:
  135.             return DefWindowProc(hWnd,Message,wParam,lParam);
  136.         }
  137.         break;
  138.     case WM_MOUSEMOVE:
  139.         if(!nDoingTopBottomAction){
  140.             return DefWindowProc(hWnd,Message,wParam,lParam);
  141.         }
  142.         hwndTemp=IsDoable(GetMessagePos());
  143.         if(hwndTemp){                   /* processable? */
  144.             if(!nShowingOkCursor){      /* need to change cursor? */
  145.                 nShowingOkCursor=1;
  146.                 SetCursor(hcOkCursor);  /* yes, change it */
  147.             }
  148.         }
  149.         else{
  150.             if(nShowingOkCursor){       /* need to change cursor? */
  151.                 nShowingOkCursor=0;
  152.                 SetCursor(hcNotOkCursor); /* yes, change it */
  153.             }
  154.         }
  155.         break;
  156.     case WM_LBUTTONDOWN:
  157.         if(!nDoingTopBottomAction){
  158.             return DefWindowProc(hWnd,Message,wParam,lParam);
  159.         }
  160.         nGotLButtonDown=1;
  161.         break;
  162.     case WM_LBUTTONUP:
  163.         if(!nDoingTopBottomAction){
  164.             return DefWindowProc(hWnd,Message,wParam,lParam);
  165.         }
  166.         if(nGotLButtonDown)TopBottomWindowAtPoint(GetMessagePos());
  167.         StopDoingTopBottomAction();
  168.         break;
  169.     case WM_LBUTTONDBLCLK:
  170.     case WM_MBUTTONDBLCLK:
  171.     case WM_RBUTTONDBLCLK:
  172.     case WM_MBUTTONUP:
  173.     case WM_RBUTTONUP:
  174.         if(nDoingTopBottomAction)StopDoingTopBottomAction();
  175.         else return DefWindowProc(hWnd,Message,wParam,lParam);
  176.         break;
  177.     case WM_CLOSE:
  178.         if(nDoingTopBottomAction)StopDoingTopBottomAction();
  179.         DestroyWindow(hWnd);
  180.         PostQuitMessage(0);
  181.         break;
  182.     default:
  183.         return DefWindowProc(hWnd,Message,wParam,lParam);
  184.     }
  185.     return 0L;
  186. }
  187. void DoTopBottomAction(int nTopOrBottom){
  188. /*
  189. **  called with DO_TOP or DO_BOTTOM, which determines whether
  190. **  the target window is floated or sunk
  191. **
  192. **  takes control of the mouse, sets nDoingTopBottomAction
  193. **  to nTopOrBottom, then returns
  194. */
  195.     LPSTR desiredcursor,desiredncursor;
  196.     if(nDoingTopBottomAction)return;
  197.     switch(nTopOrBottom){
  198.     case DO_TOP:
  199.         desiredcursor="TopCursor";
  200.         desiredncursor="NTopCursor";
  201.         break;
  202.     case DO_BOTTOM:
  203.         desiredcursor="BottomCursor";
  204.         desiredncursor="NBottomCursor";
  205.         break;
  206.     default:
  207.         return;
  208.     }
  209.     nDestroyOkCursor=nDestroyNotOkCursor=0;
  210.     hcOkCursor=LoadCursor(hInst,desiredcursor);
  211.     if(!hcOkCursor)hcOkCursor=LoadCursor(NULL,IDC_CROSS);
  212.     else nDestroyOkCursor=1;
  213.     hcNotOkCursor=LoadCursor(hInst,desiredncursor);
  214.     if(!hcNotOkCursor){
  215.         hcNotOkCursor=LoadCursor(NULL,IDC_CROSS);
  216.     }
  217.     else nDestroyNotOkCursor=1;
  218.     SetCapture(hWndMain);
  219.     hcOldCursor=SetCursor(hcOkCursor);
  220.     nShowingOkCursor=1;
  221.     nDoingTopBottomAction=nTopOrBottom;
  222.     nGotLButtonDown=0;
  223.     nSuccess=0;
  224. }
  225. void StopDoingTopBottomAction(void){
  226. /*
  227. **  if nDoingTopBottomAction, zeros it and releases mouse
  228. **  also destroys cursor(s)
  229. */
  230.     if(nDoingTopBottomAction){
  231.         nDoingTopBottomAction=0;
  232.         if(hcOldCursor)SetCursor(hcOldCursor);
  233.         else SetCursor(LoadCursor(NULL,IDC_ARROW));
  234.         if(nDestroyOkCursor){
  235.             DestroyCursor(hcOkCursor);
  236.             hcOkCursor=NULL;
  237.         }
  238.         if(nDestroyNotOkCursor){
  239.             DestroyCursor(hcNotOkCursor);
  240.             hcNotOkCursor=NULL;
  241.         }
  242.         nDestroyOkCursor=nDestroyNotOkCursor=0;
  243.         ReleaseCapture();
  244.         if(!nSuccess)MessageBeep(-1);
  245.     }
  246. }
  247. void TopBottomWindowAtPoint(long lParam){
  248. /*
  249. **  goes by nDoingTopBottomAction, which determines whether the point
  250. **  at lParam (taken from a mouse message) gets its window sent to
  251. **  the top or the bottom
  252. */
  253.     HWND hwnd=IsDoable(lParam),order;
  254.     if(!hwnd)return;
  255.     order=(nDoingTopBottomAction==DO_TOP)?HWND_TOPMOST:HWND_NOTOPMOST;
  256.     if(SetWindowPos(hwnd,order,0,0,0,0,
  257.     SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE)){
  258.         nSuccess=1;
  259.     }
  260. }
  261. HWND IsDoable(long lParam){
  262.     /*
  263.     **  takes current position, returns window handle of window that
  264.     **  should be topped or bottomed. If not possible, returns NULL.
  265.     */
  266.     HWND child,parent,desktop,order;
  267.     POINT point;
  268.     LONG extended_style;
  269.     if(!nDoingTopBottomAction)return NULL;
  270.     desktop=GetDesktopWindow();
  271.     point.x=(int)LOWORD(lParam);
  272.     point.y=(int)HIWORD(lParam);
  273.     child=WindowFromPoint(point);
  274.     if((!child)||(child==desktop))return NULL;
  275.     /*
  276.     **  ok, it's a good window
  277.     **  let's go back to the highest level
  278.     **  *before* the desktop
  279.     */
  280.     for(;;){
  281.         parent=GetParent(child);
  282.         if(!parent||(parent==desktop))break;
  283.         child=parent;
  284.     }
  285.     /*
  286.     **  now child is HWND for target app,
  287.     **  so let's find out it if can be done...
  288.     */
  289.     extended_style=GetWindowLong(child,GWL_EXSTYLE);
  290.     if(extended_style&WS_EX_TOPMOST){   /* window topped */
  291.         return (nDoingTopBottomAction==DO_BOTTOM)?child:NULL;
  292.     }
  293.     else{                               /* window not topped */
  294.         return (nDoingTopBottomAction==DO_TOP)?child:NULL;
  295.     }
  296. }
  297.