home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / PROG_C / CENVIW9.ZIP / PMITEMS.CMM < prev    next >
Text File  |  1994-03-08  |  10KB  |  339 lines

  1. // PMItems.cmm - Utility to make all PM items available from a
  2. // ver.1         list made available at any time from a tiny button
  3. //               maintained at top level on the screen.
  4. //
  5. //               This uses DDE for communicating with the program
  6. //               manager, and uses Windows function for buttons
  7. //               and an item list.
  8.  
  9. #include <Progman.lib>
  10. #include <Window.lib>
  11. #include <WinTools.lib>
  12. #include <Message.lib>
  13. #include <WinExec.lib>
  14. #include <Profile.lib>
  15. #include <MsgBox.lib>
  16.  
  17. #define BUTTON_WIDTH    10
  18. #define BUTTON_HEIGHT   15
  19. #define BUTTON_ROW      0
  20. #define BUTTON_COL      0
  21. #define BUTTON_TEXT     "i"
  22.  
  23. ItemListCount;
  24. ItemList;   // this will be initialized to contain an array of structures with
  25.             // these elements:
  26.             //    .Description - What is displayed in list to select from
  27.             //    .CommandLine - Statement to begin execution
  28.             //    .WorkingDirectory - Directory to execute from
  29.             //    .RunMinimized - Boolean on whethter to minimzed to start
  30.  
  31. main()
  32. {
  33.    ChangeToWindowsDefaultDirectory();
  34.  
  35.    SetWindowTitle(ScreenHandle(),"Building list...");
  36.    BuildItemList();
  37.    SetWindowTitle(ScreenHandle(),"Sorting list...");
  38.    SortItemList();
  39.  
  40.    SetWindowTitle(ScreenHandle(),"Making List Windows...");
  41.    ButtonHwnd = MakeItemButton();
  42.    MakeItemListbox(ButtonHwnd);
  43.  
  44.    SetWindowTitle(ScreenHandle(),"PMItems");
  45.  
  46.    // hide little icon, for noone wants to see it
  47.    ShowWindow(ScreenHandle(),SW_HIDE);
  48.  
  49.    // Keep windows on top; if version 3.1 or higher then just use the on_top
  50.    // flags, else move it to top once per few seconds
  51.    if ( GetWindowsVersion() < 0x030A ) {
  52.       // old windows version, must draw to top every few seconds (approx.)
  53.       #define ONTOP_FREQ   3     // seconds between placing on top
  54.       NextOnTopTime = 0;
  55.       while ( DoWindows(True) ) {
  56.          if ( NextOnTopTime <= clock() ) {
  57.             MoveWindowToTop3_0(ButtonHwnd);
  58.             NextOnTopTime = clock() + CLOCKS_PER_SEC * ONTOP_FREQ;
  59.          }
  60.       }
  61.    } else {
  62.       // new windows version simply draw on top
  63.       MoveWindowToTop3_1(ButtonHwnd);
  64.       while ( DoWindows() ) ;
  65.    }
  66. }
  67.  
  68.  
  69. //*************** BUILD ITEM LIST ****************
  70.  
  71. BuildItemList()
  72. {
  73.    if ( SpawnProgman = !IsProgmanRunning() ) {
  74.       // program manager is not executing, and so start it
  75.       if ( 0 == spawn(P_NOWAIT,"Progman.exe") )
  76.          FatalError("Program Manager could not be started.");
  77.    }
  78.  
  79.    ConnectToProgman();
  80.  
  81.    // get list of all the Program Manager groups
  82.    if ( !ProgmanGroups(GroupList,GroupCount) )
  83.       FatalError("No groups found in Program Manager.");
  84.  
  85.    // for each group, add to ItemList each item in the group
  86.    ItemListCount = 0;
  87.    for ( group = 0; group < GroupCount; group++ ) {
  88.       if ( !ProgmanGroupItems(GroupList[group],GroupInfo,IList) )
  89.          FatalError("Error retrieving items from group \"%s\".",GroupList[group]);
  90.       for ( item = 0; item < GroupInfo.Count; item++ ) {
  91.          ItemList[ItemListCount].Description = IList[item].Description;
  92.          ItemList[ItemListCount].CommandLine = IList[item].CommandLine;
  93.          ItemList[ItemListCount].WorkingDirectory = IList[item].WorkingDirectory;
  94.          ItemList[ItemListCount].RunMinimized = IList[item].RunMinimized;
  95.          ItemListCount++;
  96.       }
  97.    }
  98.  
  99.    CloseProgmanConnection();
  100.  
  101.    if ( SpawnProgman ) {
  102.       // Program manager was started here, and so kill it
  103.       if ( !ExitProgman(False) ) {
  104.          // wouldn't exit itself, and so send the close message
  105.          PostMessage(GetWindowHandle("Program Manager"),WM_QUIT,0,0);
  106.       }
  107.    }
  108.  
  109.    if ( 0 == ItemListCount )
  110.       FatalExit("No items were found in Program Manager");
  111. }
  112.  
  113. //*************** SORT ITEM LIST ***************
  114.  
  115. SortFunction(Item1,Item2)  // sort alphabetically by description
  116. {
  117.    return stricmp(Item1.Description,Item2.Description);
  118. }
  119.  
  120. SortItemList()
  121. {
  122.    qsort(ItemList,ItemListCount,"SortFunction");
  123. }
  124.  
  125. //*************** BUTTON AND BUTTON WINDOW ***************
  126.  
  127. MakeItemButton()
  128. {
  129.    return MakeWindow(NULL,"button","ItemButtonFunction",
  130.                   BUTTON_TEXT,WS_VISIBLE | BS_PUSHBUTTON | WS_POPUP,
  131.                   BUTTON_COL,BUTTON_ROW,
  132.                   BUTTON_WIDTH,BUTTON_HEIGHT,NULL);
  133. }
  134.  
  135. ItemButtonFunction(hwnd,msg,wparam,lparam)
  136. {
  137.    if ( BM_SETSTATE == msg  &&  !wparam ) {
  138.       // Button was clicked, so show item list if not already showing
  139.       ShowItemListbox();
  140.    }
  141. }
  142.  
  143. //*************** ITEM LIST LISTBOX ***************
  144.  
  145. #define LISTBOX_COL     0
  146. #define LISTBOX_ROW     0
  147. #define LISTBOX_WIDTH   250
  148. #define LISTBOX_HEIGHT  500
  149.  
  150. ListHwnd;
  151.  
  152. MakeItemListbox(ButtonHwnd) // create listbox hidden
  153. {
  154.    ListHwnd= MakeWindow(ButtonHwnd,"listbox","ListBoxFunction",
  155.               "PM Items",WS_CAPTION | WS_POPUP | WS_VSCROLL | WS_HSCROLL,
  156.               LISTBOX_COL,LISTBOX_ROW,LISTBOX_WIDTH,LISTBOX_HEIGHT,NULL);
  157.    // fill listbox with all our choices
  158.    for ( i = 0; i < ItemListCount; i++ ) {
  159.       SendMessage(ListHwnd,LB_ADDSTRING,0,ItemList[i].Description);
  160.    }
  161. }
  162.  
  163. ListBoxFunction(hwnd,msg,wparam,lparam)
  164. {
  165.    switch ( msg ) {
  166.       case WM_CHAR:
  167.          switch ( wparam ) {
  168.             case '\r':
  169.                ListboxExecuteCurrentSelection();
  170.                return 0;
  171.             case 0x1B: // escape
  172.                HideItemListbox();
  173.                return 0;
  174.          }
  175.          break;
  176.       case WM_LBUTTONDBLCLK:
  177.          ListboxExecuteCurrentSelection();
  178.          break;
  179.       case WM_KILLFOCUS:
  180.          HideItemListbox()
  181.          break;
  182.    }
  183. }
  184.  
  185. ShowItemListbox()
  186. {
  187.    ShowWindow(ListHwnd,SW_RESTORE);
  188. }
  189.  
  190. HideItemListbox()
  191. {
  192.    ShowWindow(ListHwnd,SW_HIDE);
  193. }
  194.  
  195. ListboxExecuteCurrentSelection()
  196. {
  197.    HideItemListbox();
  198.    SelectionIndex = SendMessage(ListHwnd,LB_GETCURSEL,0,0);
  199.    if ( LB_ERR != SelectionIndex ) {
  200.       Selection = ItemList[SelectionIndex];
  201.       SetCurrentDirectory(Selection.WorkingDirectory);
  202.  
  203.       ExecuteCommandLine(Selection.CommandLine,Selection.WorkingDirectory,Selection.RunMinimized);
  204.    }
  205. }
  206.  
  207. ExecuteCommandLine(pCmd,pDir,pRunMinimized)
  208. {  // pCmd may specify a file with an extension association, in which case
  209.    // it would be correct to run that extension program.  Also may combine
  210.    // directory with Cmd to get full execution name.
  211.    strcpy(lCmd,pCmd);
  212.  
  213.    // Use pDir, if necessary and available, to get full path for lCmd
  214.    if ( pDir[0]  &&  lCmd[1] != ':' ) {
  215.       // Get full path of directory
  216.       if ( !(lDir = FullPath(pDir)) ) {
  217.          Error("Invalid Working Directory \"%s\"\n",pDir);
  218.          return;
  219.       }
  220.       // add cmd to appropriate end of the path
  221.       if ( lCmd[0] == '\\' ) {
  222.          // cmd starts at root dir, so only use working dir drive
  223.          sprintf(lCmd,"%c:%s",lDir[0],lCmd);
  224.       } else {
  225.          // append command to full working directory
  226.          if ( !strcmp(lDir+1,":\\") ) lDir[2] = 0;
  227.          sprintf(lCmd,"%s\\%s",lDir,lCmd);
  228.       }
  229.    }
  230.  
  231.    // get file name with whatever parameters may follow
  232.    if ( lCmdSaveBlank = strchr(pCmd,' ') ) lCmdSaveBlank[0] = 0;
  233.    strcpy(lExtension,SplitFileName(pCmd).ext);
  234.    if ( lExtension[1] ) {
  235.       lAssociation = GetProfileString("Extensions",lExtension+1,"");
  236.       if ( lAssociation[0] ) {
  237.          // remove beyond first blank or '^' character
  238.          if ( lEndSpec = strpbrk(lAssociation," ^\t") )
  239.             lEndSpec[0] = 0;
  240.       }
  241.    }
  242.    if ( lCmdSaveBlank ) lCmdSaveBlank[0] = ' ';
  243.  
  244.    if ( defined(lAssociation)  &&  lAssociation[0] )
  245.       sprintf(lCmd,"%s %s",lAssociation,lCmd);
  246.  
  247.    ExecResult = WinExec( lCmd, pRunMinimized ? SW_MINIMIZE : SW_SHOWNORMAL );
  248.    if ( ExecResult < 32 )
  249.       Error("Error %d on call to WinExec() for command:\n\"%s\"",ExecResult,lCmd);
  250. }
  251.  
  252. //*************** UTILITY FUNCTIONS ***************
  253.  
  254.  
  255. FatalError(FormatString/*,arg,arg,arg*/) // display printf-like error message
  256. {
  257.    va_start(va_list,FormatString);
  258.    vsprintf(msg,FormatString,va_list);
  259.    MessageBox(msg,"ERROR!",MB_ICONEXCLAMATION);
  260.    va_end(va_list);
  261.    exit(EXIT_FAILURE);
  262. }
  263.  
  264. Error(FormatString/*,arg,arg,arg*/) // display printf-like error message
  265. {
  266.    va_start(va_list,FormatString);
  267.    vsprintf(msg,FormatString,va_list);
  268.    MessageBox(msg,"ERROR!",MB_ICONEXCLAMATION);
  269.    va_end(va_list);
  270. }
  271.  
  272.  
  273. SetCurrentDirectory(pDir)
  274. {
  275.    if ( NULL != (lDir = pDir)  &&  0 != lDir[0] ) {
  276.       if ( ':' == lDir[1] ) {
  277.          // set drive
  278.          reg.ah = 0xE;
  279.          reg.dl = toupper(lDir[0]) - 'A';
  280.          interrupt(0x21,reg);
  281.          lDir += 2;
  282.       }
  283.       if ( lDir[0] ) {
  284.          // set directory
  285.          reg.ah = 0x3B;
  286.          reg.ds = segment(lDir), reg.dx = offset(lDir);
  287.          interrupt(0x21,reg);
  288.       }
  289.    }
  290. }
  291.  
  292. ChangeToWindowsDefaultDirectory()
  293. {
  294.    SetCurrentDirectory(GetWindowsDirectory());
  295. }
  296.  
  297. GetWindowsDirectory()
  298. {
  299.    lWinDir[0] = lWinDir[400] = '\0';
  300.    lWinDir[DynamicLink("KERNEL","GETWINDOWSDIRECTORY",UWORD16,PASCAL,lWinDir,399)] = 0;
  301.    return lWinDir;
  302. }
  303.  
  304. GetWindowsVersion()  // return major version in hi byte, and minor in low
  305. {                    // so 3.1 is 0x030A
  306.    lVers = DynamicLink("KERNEL","GETVERSION",UWORD16,PASCAL);
  307.    return ((lVers & 0xFF00) >> 8) | ((lVers & 0xFF) << 8);
  308. }
  309.  
  310. MoveWindowToTop3_0(pHwnd)
  311. {
  312.    #define HWND_TOP  0
  313.  
  314.    /* SetWindowPos Flags */
  315.    #define SWP_NOSIZE          0x0001
  316.    #define SWP_NOMOVE          0x0002
  317.    #define SWP_NOZORDER        0x0004
  318.    #define SWP_NOREDRAW        0x0008
  319.    #define SWP_NOACTIVATE      0x0010
  320.    #define SWP_DRAWFRAME       0x0020
  321.    #define SWP_SHOWWINDOW      0x0040
  322.    #define SWP_HIDEWINDOW      0x0080
  323.    #define SWP_NOCOPYBITS      0x0100
  324.    #define SWP_NOREPOSITION    0x0200
  325.    DynamicLink("USER","SETWINDOWPOS",SWORD16,PASCAL,
  326.                pHwnd,HWND_TOP,0,0,0,0,
  327.                SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE);
  328. }
  329.  
  330. MoveWindowToTop3_1(pHwnd)
  331. {
  332.    #define HWND_TOPMOST    -1
  333.    DynamicLink("USER","SETWINDOWPOS",SWORD16,PASCAL,
  334.                pHwnd,HWND_TOPMOST,0,0,0,0,
  335.                SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE);
  336. }
  337.  
  338.  
  339.