//=========================================================== // LC - Launch Control, Fine tunes launching applications // // Copyright (C) 1995 Ziff-Davis Publishing Company // First published in PC Magazine by Douglas Boling // // Revision History: // // 1.0 Initial Release // //=========================================================== #include "windows.h" #include "shellapi.h" #include "commdlg.h" #include "dde.h" #include "stdlib.h" #include "string.h" #include "direct.h" #include "dos.h" #include "lc.h" // Returns no. of elements #define dim(x) (sizeof(x) / sizeof(x[0])) #define MAXCMDLINELEN 256 #define ID_TIMER 1 // // Custom messages // #define MYMSG_LAUNCHPROG WM_USER + 100 //----------------------------------------------------------- // Include files //----------------------------------------------------------- //----------------------------------------------------------- // Global data //----------------------------------------------------------- // Message dispatch table for MainWindowProc struct decodeUINT MainMessages[] = { WM_CREATE, DoCreateMain, WM_SIZE, DoSizeMain, WM_TIMER, DoTimerMain, MYMSG_LAUNCHPROG, DoLaunchProgMain, WM_DDE_INITIATE, DoDDEWorkMain, WM_DDE_REQUEST, DoDDEWorkMain, WM_DDE_TERMINATE, DoDDEWorkMain, WM_COMMAND, DoCommandMain, WM_CLOSE, DoCloseMain, WM_DESTROY, DoDestroyMain, }; // Command Message dispatch for MainWindowProc struct decodeCMD MainMenuItems[] = { IDM_NEW, DoMainMenuNew, IDM_OPEN, DoMainMenuOpen, IDM_SAVE, DoMainMenuSave, IDM_SAVEAS, DoMainMenuSaveAs, IDM_ABOUT, DoMainCtlAbout, IDM_EXIT, DoMainCtlExit, IDCANCEL, DoMainCtlExit, IDD_CMD, DoMainCtlCmd, IDD_RBENV, DoMainCtlRButtons, IDD_RBSIZE, DoMainCtlRButtons, IDD_RBDOS, DoMainCtlRButtons, IDD_RF1, DoMainCtlRBStart, IDD_RF2, DoMainCtlRBStart, IDD_RF3, DoMainCtlRBStart, IDD_ENVA, DoMainCtlRBEnv, IDD_ENVB, DoMainCtlRBEnv, IDD_SIZEA, DoMainCtlChkBoxes, IDD_DOSA, DoMainCtlChkBoxes, IDD_BROWSE, DoMainCtlBrowse, IDD_ENVEDIT, DoMainCtlEnvEdit, IDD_DOSSETICON, DoMainCtlSetIcon, IDD_DOSIBOX, DoMainCtlDOSIBox, }; HANDLE hInst; HWND hMain; INT sTimerFreq; HINSTANCE h3DLib = 0; INT sVer = 10; INT sHPos, sVPos, sHSize, sVSize; char szTemp[512]; char szStartDir[256] = ""; INT fMainFlags = MFLAG_FIRST; // Structure that holds program info MYPROGDATA Prog; // Handle and ptr to environment HGLOBAL hDefEnv; LPSTR lpDefEnv; // Handle and ptr to new variables HGLOBAL hEnv; LPSTR lpEnv; // Vars for DDE com with WinOldApp. char *pLaunch = 0; HINSTANCE hLastLaunch; // List of icon library files struct { char szName[128]; } IconLibs[16] = {"progman.exe", "moricons.dll"}; INT sIconLibCnt = 2; char szAppName[] = "LaunchCtl"; // Application name char szIconName[] = "LaunchCtlIcon"; // Icon name char szMenuName[] = "LaunchCtlMenu"; // Menu name char szTitleText[] = "LaunchCtl"; // Window title text char szProfileName[128]; // INI file name char szDataFileName[128] = ""; char szFileTag[] = "LaunchCtl Data File 1.0 DMB\n"; char szDebug [256]; //============================================================ // WinMain -- entry point for this application from Windows. //============================================================ INT APIENTRY WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow) { MSG msg; INT rc; hInst = hInstance; if (hPrevInstance == 0) { rc = InitApp(hInstance); if (rc) return rc; } // Initialize this instance if((rc = InitInstance(hInstance, lpCmdLine, nCmdShow)) != 0) return rc; // // Application message loop // while (GetMessage (&msg, NULL, 0, 0)) { if (!IsDialogMessage (hMain, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } // Instance cleanup return TermInstance(hInstance, msg.wParam); } //----------------------------------------------------------- // InitApp - Global initialization code for this application. //----------------------------------------------------------- INT InitApp(HANDLE hInstance) { WNDCLASS wc; // // Register App Main Window class // wc.style = 0; // Window style wc.lpfnWndProc = MainWndProc; // Callback function wc.cbClsExtra = 0; // Extra class data wc.cbWndExtra = DLGWINDOWEXTRA; // Extra window data wc.hInstance = hInstance; // Owner handle wc.hIcon = LoadIcon(hInst, szIconName); // Application icon wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Default cursor wc.hbrBackground = GetStockObject(LTGRAY_BRUSH); // Background color wc.lpszMenuName = szMenuName; // Menu name wc.lpszClassName = szAppName; // Window class name if (RegisterClass(&wc) == 0) return 1; return 0; } //----------------------------------------------------------- // InitInstance - Instance initialization code for this app. //----------------------------------------------------------- INT InitInstance(HANDLE hInstance, LPSTR lpCmdLine, INT nCmdShow) { int i, j, rc; char **pEnv; LPSTR lpTmp; FARPROC lp3dproc; BOOL fRun = TRUE; // If 3DLib present, load it for 3d effects. h3DLib = LoadLibrary ("CTL3D.DLL"); if (h3DLib < HINSTANCE_ERROR) h3DLib = 0; else { lp3dproc = GetProcAddress (h3DLib, "Ctl3dRegister"); if (lp3dproc) (*lp3dproc) (hInst); else { FreeLibrary (h3DLib); h3DLib = 0; } } //Create INI filename GetModuleFileName (hInst, szProfileName, sizeof (szProfileName)); for (i = lstrlen (szProfileName); i && szProfileName[i] != '.'; --i); lstrcpy (&szProfileName[i], ".INI"); // Create an environment blocks hDefEnv = GlobalAlloc (GHND, 0x10000); lpDefEnv = GlobalLock (hDefEnv); lpTmp = lpDefEnv; if (lpTmp) { pEnv = environ; while (*pEnv) { lstrcpy (lpTmp, *pEnv++); if (lstrlen (lpTmp)) lpTmp += lstrlen (lpTmp) + 1; } *lpTmp = '\0'; } else hDefEnv = 0; hEnv = GlobalAlloc (GHND, 0x10000); lpEnv = GlobalLock (hEnv); *(LPWORD)lpEnv = 0; // Init PROG structure memset (&Prog, 0, sizeof (Prog)); Prog.wStartFlags = START_DEFENV | START_DEFSIZE; sTimerFreq = GetPrivateProfileInt (szAppName, PRO_TIMERFREQ, 256, szProfileName); if (*lpCmdLine) { // See if /l used to load file with out executing if ((*lpCmdLine == '/') || (*lpCmdLine == '-')) { lpCmdLine++; if ((*lpCmdLine == 'l') || (*lpCmdLine == 'L')) { lpCmdLine++; fRun = FALSE; } } // Skip over any leading spaces while ((*lpCmdLine) && (*lpCmdLine <= ' ')) lpCmdLine++; lstrcpy (szDataFileName, lpCmdLine); rc = OpenDataFile (lpCmdLine, &Prog, lpEnv); if (rc) { PrintError (0, rc); return (rc); } else { if (fRun) fMainFlags |= MFLAG_LAUNCH; } } i = GetPrivateProfileInt (szAppName, PRO_XPOS, 100, szProfileName); j = GetPrivateProfileInt (szAppName, PRO_YPOS, 100, szProfileName); // Create main window hMain = CreateDialog (hInstance, szAppName, 0, NULL); if(!hMain) return 0x10; SetWindowPos (hMain, NULL, i, j, 0, 0, SWP_NOSIZE); SetTitle (hMain); if (fMainFlags & MFLAG_LAUNCH) { PostMessage (hMain, MYMSG_LAUNCHPROG, 0, (LPARAM)(LPMYPROGDATA)&Prog); ShowWindow(hMain, SW_MINIMIZE); } else { ShowWindow(hMain, nCmdShow); UpdateWindow(hMain); // force WM_PAINT message } return 0; } //------------------------------------------------------------ // TermInstance - Instance termination code for this app. //------------------------------------------------------------ INT TermInstance(HANDLE hInstance, int sDefRC) { FARPROC lp3dproc; if (hDefEnv) { GlobalUnlock (hDefEnv); GlobalFree (hDefEnv); } if (hEnv) { GlobalUnlock (hEnv); GlobalFree (hEnv); } if (h3DLib) { lp3dproc = GetProcAddress (h3DLib, "Ctl3dUnregister"); if (lp3dproc) (*lp3dproc) (hInstance); FreeLibrary (h3DLib); } return sDefRC; } //============================================================ // Message handling procedures for MainWindow //============================================================ //------------------------------------------------------------ // MainWndProc - Callback function for application window //------------------------------------------------------------ LONG CALLBACK MainWndProc(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) { INT i; // // Search message list to see if we need to handle this // message. If in list, call procedure. // for(i = 0; i < dim(MainMessages); i++) { if(wMsg == MainMessages[i].Code) return (*MainMessages[i].Fxn)(hWnd, wMsg, wParam, lParam); } return DefDlgProc(hWnd, wMsg, wParam, lParam); } //------------------------------------------------------------ // DoCreateMain - process WM_CREATE message for frame window. //------------------------------------------------------------ LONG DoCreateMain (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) { FARPROC lp3dproc; if (h3DLib) { lp3dproc = GetProcAddress (h3DLib, "Ctl3dSubclassDlgEx"); if (lp3dproc) { (*lp3dproc) (hWnd, -1); } } return 0; } //------------------------------------------------------------ // DoSizeMain - process WM_SIZE message for frame window. //------------------------------------------------------------ LONG DoSizeMain (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) { FARPROC lp3dproc; if (fMainFlags & MFLAG_FIRST) { fMainFlags &= ~MFLAG_FIRST; if (h3DLib) { lp3dproc = GetProcAddress (h3DLib, "Ctl3dSubclassDlgEx"); if (lp3dproc) { (*lp3dproc) (hWnd, -1); } } SetControls (hWnd, &Prog, lpEnv); if (Prog.wStartFlags & START_DOSLAUNCH) SendMessage (hWnd, WM_COMMAND, IDD_RBDOS, MAKELPARAM (0, BN_CLICKED)); } return DefDlgProc(hWnd, wMsg, wParam, lParam); } //------------------------------------------------------------ // DoTimerMain - process WM_TIMER message for frame window. //------------------------------------------------------------ LONG DoTimerMain (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) { HWND hHandle; LONG lStyle; UINT usFlags; INT cx, cy; WINDOWPLACEMENT wp; hHandle = GetWindow (GetDesktopWindow(), GW_CHILD); while (hHandle) { GetModuleFileName (GetWindowWord (hHandle, GWW_HINSTANCE), szTemp, sizeof (szTemp)); lStyle = GetWindowLong (hHandle, GWL_STYLE); if (!(lStyle & (WS_CHILD | WS_POPUP)) && (lStyle & WS_VISIBLE)) { if (GetWindowWord (hHandle, GWW_HINSTANCE) == hLastLaunch) { if (!(Prog.wStartFlags & START_DEFSIZE)) { if (!IsZoomed (hHandle) && !IsIconic (hHandle)) { // See if we can set the size of a window if (lStyle & WS_THICKFRAME) usFlags = SWP_NOZORDER; else usFlags = SWP_NOSIZE | SWP_NOZORDER; // Compute new size and pos. If -1's in rect, use // default for those measurments. if ((Prog.rect.left == -1) || (Prog.rect.right == -1)) usFlags = SWP_NOMOVE; if ((Prog.rect.top == -1) || (Prog.rect.bottom == -1)) usFlags = SWP_NOSIZE; // Limit position to on screen values. cx = GetSystemMetrics (SM_CXSCREEN); cy = GetSystemMetrics (SM_CYSCREEN); if (Prog.rect.left > cx) Prog.rect.left = cx - GetSystemMetrics (SM_CXSIZE); if (Prog.rect.top > cy) Prog.rect.top = cy - GetSystemMetrics (SM_CYSIZE); SetWindowPos (hHandle, 0, Prog.rect.left, Prog.rect.top, Prog.rect.right, Prog.rect.bottom, usFlags); } else { // If minimized or maxed, use SetWindowPlacment to // modify the future pos of the restored window. memset (&wp, 0, sizeof (wp)); wp.length = sizeof (wp); GetWindowPlacement (hHandle, &wp); // Compute new size and pos. If -1's in rect, use // default for those measurments. cx = wp.rcNormalPosition.right - wp.rcNormalPosition.left; cy = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top; if ((Prog.rect.top != -1) && (Prog.rect.bottom != -1)) { cx = Prog.rect.right; cy = Prog.rect.bottom; } if ((Prog.rect.left != -1) && (Prog.rect.right != -1)) { wp.rcNormalPosition.left = Prog.rect.left; wp.rcNormalPosition.top = Prog.rect.top; } wp.rcNormalPosition.right = wp.rcNormalPosition.left + cx; wp.rcNormalPosition.bottom = wp.rcNormalPosition.top + cy; SetWindowPlacement (hHandle, &wp); } } KillTimer (hWnd, ID_TIMER); PostMessage (hWnd, WM_CLOSE, 0, 0); break; } } hHandle = GetWindow (hHandle, GW_HWNDNEXT); } return 0; } //------------------------------------------------------------ // WinExecEnv - WinExec call that also allows a custom // environment. // // This function performs a DOS exec call. Windows' DOS // extender will catch and translate into LoadModule. We // can't use LoadModule directly because LM doesn't know // how to handle DOS apps. // //------------------------------------------------------------ HINSTANCE WinExecEnv (LPSTR lpProg, LPSTR lpTail, LPSTR lpDir, UINT wShow, WORD wEnvSeg) { struct { WORD segEnv; LPSTR lpszCmdLine; LPWORD lpwShow; LPWORD lpwReserved; } exec_struct; WORD wShowArray[2]; HINSTANCE hExec; char szName[128], szTail[128]; LPSTR lpEnd; union REGS inregs, outregs; lstrcpy (szName, lpProg); // Tail must be length byte followed by tail terminated by CR if (lpTail) lstrcpy (&szTail[1], lpTail); else szTail[1] = '\0'; szTail[0] = (char)lstrlen (&szTail[1]); lpEnd = &szTail[1] + (INT)szTail[0]; *lpEnd++ = 0x0d; *lpEnd = '\0'; // Init show array. LoadMod requires that the first int be set to 2. wShowArray[0] = 2; wShowArray[1] = wShow; exec_struct.segEnv = wEnvSeg; exec_struct.lpszCmdLine = szTail; exec_struct.lpwShow = wShowArray; exec_struct.lpwReserved = 0; // DOS Exec inregs.x.ax = 0x4b00; inregs.x.bx = (WORD)&exec_struct; inregs.x.dx = (WORD)szName; intdos (&inregs, &outregs); hExec = outregs.x.ax; return hExec; } //------------------------------------------------------------ // MyDOSLaunch - //------------------------------------------------------------ BOOL MyDOSLaunch (LPSTR lpCmdPath) { char szLCName[128]; char szTail[128]; union REGS inregs, outregs; INT i, sID = 0; // Search for WinGo and disable if present for (i = 0xdb; i < 0x100; i++) { inregs.x.ax = i << 8; inregs.x.cx = 0; inregs.x.dx = 0; int86 (0x2f, &inregs, &outregs); if ((outregs.h.al) && (outregs.x.cx == 0x5749) && (outregs.x.dx == 0x4e47)) { inregs.h.ah = (char)i; inregs.h.al = 5; //Get WinGo status int86 (0x2f, &inregs, &outregs); // If enabled, disable if ((outregs.x.ax == 0) && outregs.x.dx) { sID = i; inregs.h.ah = (char)i; inregs.h.al = 4; //Disable WinGo int86 (0x2f, &inregs, &outregs); } break; } } GetModuleFileName (hInst, szLCName, sizeof (szLCName)); // If WinGo was disabled, pass ID to dos part to re-enable it. if (sID) wsprintf (szTail, "/w %d ", sID); else lstrcpy (szTail, "/l "); lstrcat (szTail, szDataFileName); lstrcat (szTail, " "); lstrcat (szTail, lpCmdPath); lstrcat (szTail, " *"); return ExitWindowsExec (szLCName, szTail); } //------------------------------------------------------------ // FindAndDel - Scans env blk for var and deletes //------------------------------------------------------------ LPSTR FindAndDel (LPSTR lpStart, LPSTR lpVar) { LPSTR lpTemp, lpDest, lpMark; INT i, sLen; // Find length of var name lpTemp = lpVar; for (i = 0; *lpTemp && (*lpTemp != '='); i++) lpTemp++; if (*lpTemp == '=') sLen = i + 1; //Inc = in comparison else sLen = -1; //Bad var, no comparison while (*lpStart) { // Compare var name to current var lpTemp = lpVar; lpDest = lpStart; for (i = 0; (i < sLen) && *lpDest && (*lpTemp == *lpDest); i++) { lpTemp++; lpDest++; } // If match, delete var by copying rest of blk over it. if (i == sLen) { lpTemp = lpStart + lstrlen (lpStart) + 1; lpMark = lpStart; if (*lpTemp) { while (*lpTemp) while (*lpStart++ = *lpTemp++) ; *lpStart = '\0'; } else *lpStart = '\0'; lpStart = lpMark; } else // Look at next var lpStart = lpStart + lstrlen (lpStart) + 1; } // Re-terminate env blk with dup zeros. *lpStart = '\0'; return lpStart; } //------------------------------------------------------------ // DoLaunchProgMain - process MYMSG_LAUNCHPROG message //------------------------------------------------------------ LONG DoLaunchProgMain (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) { HINSTANCE hExecInst; INT wShow; LPMYPROGDATA lpProg; LPSTR lpEnd, lpLEnv, lpLEnvEnd; char ch, szTemp[129]; char szTruePath[128]; HCURSOR hOld; HGLOBAL hLaunchEnv, hTemp; if (lParam == 0) return 0; lpProg = (LPMYPROGDATA) lParam; // Create an environment blocks hLaunchEnv = GlobalAlloc (GHND, 0x10000); lpLEnv = GlobalLock (hLaunchEnv); lpLEnvEnd = lpLEnv; *(LPINT)lpLEnvEnd = 0; if (lpProg->wStartFlags & START_DEFENV) { lpEnd = lpDefEnv; while (*lpEnd) { lstrcpy (lpLEnvEnd, lpEnd); // Move end of env ptr past added var lpLEnvEnd += lstrlen (lpLEnvEnd) + 1; // Point to next new var lpEnd += lstrlen (lpEnd) + 1; } } // Point to blk containing new env vars lpEnd = lpEnv; while (*lpEnd) { // Del any prev instances of var in blk lpLEnvEnd = FindAndDel (lpLEnv, lpEnd); lstrcpy (lpLEnvEnd, lpEnd); // Point to next new var lpEnd += lstrlen (lpEnd) + 1; // Move end of env ptr past added var then term env lpLEnvEnd += lstrlen (lpLEnvEnd) + 1; *lpLEnvEnd++ = 0; } // Resize env blk GlobalUnlock (hLaunchEnv); hTemp = GlobalReAlloc (hLaunchEnv, lpLEnvEnd - lpLEnv + 15, GMEM_ZEROINIT); if (hTemp) hLaunchEnv = hTemp; // Set show parameter if (lpProg->wStartFlags & START_MIN) wShow = SW_SHOWMINIMIZED; else if (lpProg->wStartFlags & START_MAX) wShow = SW_SHOWMAXIMIZED; else wShow = SW_SHOWNORMAL; //Get complete path name for program launch lstrcpy (szTemp, lpProg->szCmd); lpEnd = GetEndofName (szTemp); // Find end of file name ch = *lpEnd; *lpEnd = '\0'; // Call Shell.dll to get association hExecInst = FindExecutable (szTemp, lpProg->szDir, szTruePath); if (hExecInst > 32) { // Launch the program if (lpProg->wStartFlags & START_DOSLAUNCH) { //If DOS launch, save .lcd file with current path of cmd MyDOSLaunch (szTruePath); PostMessage (hWnd, WM_CLOSE, 0, 0); return 0; } else { // Set working directory if (lstrlen (lpProg->szDir) != 0) { if (lpProg->szDir[1] == ':') { //UCase drive letter & convert to num. _chdrive ((lpProg->szDir[0] & 0xdf) - 0x40); } lstrcpy (szTemp, lpProg->szDir); chdir (szTemp); } // If any params, create ptr to them if (ch) *lpEnd = ch; else lpEnd = 0; hOld = SetCursor (LoadCursor (NULL, IDC_WAIT)); hExecInst = WinExecEnv (szTruePath, lpEnd, lpProg->szDir, wShow, hLaunchEnv); SetCursor (hOld); } } // If good launch, save data for DDE query if (hExecInst <= 32) { PrintError (hWnd, ERR_LAUNCH + hExecInst); PostMessage (hWnd, WM_CLOSE, 0, 0); } else { hLastLaunch = hExecInst; SetTimer (hWnd, ID_TIMER, sTimerFreq, NULL); } GlobalUnlock (hLaunchEnv); GlobalFree (hLaunchEnv); return 0; } //------------------------------------------------------------ // DoDDEWorkMain - process WM_DDE_xxx messages //------------------------------------------------------------ LONG DoDDEWorkMain (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) { char szAtomName[80]; HWND hWndOldApp; HINSTANCE hExecInst; LPSTR lpData, lpIcon; MYPROGDATA *pProg; HGLOBAL hData; HICON hIcon; UINT wOffset; INT wSize, rc; hWndOldApp = (HWND)wParam; switch (wMsg) { case WM_DDE_INITIATE: // See if addressing the Shell GlobalGetAtomName (LOWORD (lParam), szAtomName, sizeof (szAtomName)); if (lstrcmpi (szAtomName, "Shell") == 0) { // See if App properties topic GlobalGetAtomName (HIWORD (lParam), szAtomName, sizeof (szAtomName)); if (lstrcmpi (szAtomName, "AppProperties") == 0) SendMessage ((HWND) wParam, WM_DDE_ACK, hWnd, lParam); } return 0; case WM_DDE_REQUEST: rc = 0; hExecInst = LOWORD (lParam); // See if reqesting info on last launched app if (hExecInst == hLastLaunch) { // Allocate mem for DDE data hData = GlobalAlloc (GMEM_DDESHARE | GHND, 0x10000); if (hData) lpData = GlobalLock (hData); else rc = 2; if (rc) { // Post a negitive ack msg PostMessage ((HWND) wParam, WM_DDE_ACK, hWnd, MAKELPARAM (0, HIWORD (lParam))); return 0; } // Init DDEDATA structure ((DDEDATA far *)lpData)->fRelease = 1; ((DDEDATA far *)lpData)->cfFormat = CF_TEXT; // See what information being requested GlobalGetAtomName (HIWORD (lParam), szAtomName, sizeof (szAtomName)); pProg = &Prog; if (lstrcmpi (szAtomName, "GetDescription") == 0) { // Copy prog description string lstrcpy (((DDEDATA far *)lpData)->Value, pProg->szDesc); } else if (lstrcmpi (szAtomName, "GetWorkingDIR") == 0) { // Copy working directory string lstrcpy (((DDEDATA far *)lpData)->Value, pProg->szDir); } else if (lstrcmpi (szAtomName, "GetIcon") == 0) { rc = 0; hIcon = GetBestIcon ((LPMYPROGDATA)pProg, 0); if (hIcon > 1) { lpIcon = GlobalLock ((HGLOBAL)hIcon); if (lpIcon) { ((LPICONPROPS)lpData)->cfFormat = 0; ((LPICONPROPS)lpData)->nWidth = *(LPWORD)(lpIcon+4); ((LPICONPROPS)lpData)->nHeight = *(LPWORD)(lpIcon+6); ((LPICONPROPS)lpData)->nPlanes = *(lpIcon+0xa); ((LPICONPROPS)lpData)->nBitsPixel = *(lpIcon+0xb); wOffset = OFFSETOF (lpData) + sizeof (ICONPROPS); wSize = (((LPICONPROPS)lpData)->nWidth * ((LPICONPROPS)lpData)->nHeight) / 8; lpIcon += 0x0c; ((LPICONPROPS)lpData)->lpANDbits = MAKELP (0, wOffset); _fmemmove (lpData + wOffset, lpIcon, wSize); wOffset += wSize; lpIcon += wSize; wSize = (((LPICONPROPS)lpData)->nWidth * ((LPICONPROPS)lpData)->nHeight * ((LPICONPROPS)lpData)->nBitsPixel) / 8; ((LPICONPROPS)lpData)->lpXORbits = MAKELP (0, wOffset); _fmemmove (lpData + wOffset, lpIcon, wSize); GlobalUnlock ((HGLOBAL)hIcon); } else rc = 1; DestroyIcon (hIcon); } else rc = 1; if (rc) { GlobalUnlock (hData); GlobalFree (hData); // Post a negitive ack msg PostMessage ((HWND) wParam, WM_DDE_ACK, hWnd, MAKELPARAM (0, HIWORD (lParam))); return 0; } } else { GlobalUnlock (hData); GlobalFree (hData); // Post a negitive ack msg PostMessage ((HWND) wParam, WM_DDE_ACK, hWnd, MAKELPARAM (0, HIWORD (lParam))); return 0; } GlobalUnlock (hData); // Respond to the message PostMessage ((HWND) wParam, WM_DDE_DATA, hWnd, MAKELPARAM (hData, HIWORD (lParam))); } break; case WM_DDE_TERMINATE: break; } return 0; } //------------------------------------------------------------ // DoCommandMain - process WM_COMMAND message for frame window // by decoding the menubar item with the menuitems[] array, // then running the corresponding function to process the command. //------------------------------------------------------------ LONG DoCommandMain (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) { INT i; UINT idItem, wNotifyCode; HWND hwndCtl; idItem = (UINT) wParam; // Parse Parameters hwndCtl = (HWND) LOWORD(lParam); wNotifyCode = (UINT) HIWORD(lParam); // // Call routine to handle control message // for(i = 0; i < dim(MainMenuItems); i++) { if(idItem == MainMenuItems[i].Code) return (*MainMenuItems[i].Fxn)(hWnd, idItem, hwndCtl, wNotifyCode); } return DefDlgProc(hWnd, wMsg, wParam, lParam); } //------------------------------------------------------------ // DoCloseMain - process WM_CLOSE message for frame window. //------------------------------------------------------------ LONG DoCloseMain (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) { INT rc = 0; // If dirty query user for save. if ((fMainFlags & MFLAG_DIRTY) && !(fMainFlags & MFLAG_LAUNCH)) { rc = MessageBox (hWnd, "Would you like to save current changes?", szTitleText, MB_YESNOCANCEL | MB_ICONEXCLAMATION); if (rc == IDCANCEL) return 0; if (rc == IDYES) rc = (INT)SendMessage (hWnd, WM_COMMAND, IDM_SAVE, 0); } DestroyWindow (hWnd); return DefDlgProc(hWnd, wMsg, wParam, lParam); } //------------------------------------------------------------ // DoDestroyMain - process WM_DESTROY message for frame window. //------------------------------------------------------------ LONG DoDestroyMain (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) { RECT rect; //Save Window position if (!IsIconic (hWnd)) { GetWindowRect (hWnd, &rect); MyWritePrivateProfileInt (szAppName, PRO_XPOS, rect.left, 10, szProfileName); MyWritePrivateProfileInt (szAppName, PRO_YPOS, rect.top, 10, szProfileName); } MyWritePrivateProfileInt (szAppName, PRO_TIMERFREQ, sTimerFreq, 10, szProfileName); PostQuitMessage (0); return DefDlgProc(hWnd, wMsg, wParam, lParam); } //============================================================ // Menu handling procedures for MainWindow //============================================================ //------------------------------------------------------------ // SetTitle - Set window title with working file included //------------------------------------------------------------ INT SetTitle (HWND hWnd) { char *pszStr; char szTemp[150]; // Set title text lstrcpy (szTemp, szTitleText); if (lstrlen (szDataFileName)) { lstrcat (szTemp, " - "); pszStr = strrchr (szDataFileName, '\\'); if (!pszStr) pszStr = szDataFileName; else pszStr++; lstrcat (szTemp, pszStr); } SetWindowText (hWnd, szTemp); return 0; } //------------------------------------------------------------ // DoMainMenuNew - Process Open menu item //------------------------------------------------------------ LONG DoMainMenuNew (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { //Clear program data memset (&Prog, 0, sizeof (Prog)); Prog.wStartFlags = START_DEFSIZE | START_DEFENV; szDataFileName[0] = '\0'; *(LPWORD)lpEnv = 0; // Reflect data to controls SetControls (hWnd, &Prog, lpEnv); // Set window title SetTitle (hWnd); return 0; } //------------------------------------------------------------ // DoMainMenuOpen - Process Open menu item //------------------------------------------------------------ LONG DoMainMenuOpen (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { char szStr[128]; static char *szFilter[] = {"LaunchCtl Files", "*.LCD", "All Files (*.*)", "*.*", "" }; INT rc; if (MyGetFilename (hWnd, szStr, sizeof (szStr), *szFilter, 1) == 0) return TRUE; rc = OpenDataFile (szStr, &Prog, lpEnv); if (rc) PrintError (hWnd, rc); else { // Set Window controls SetControls (hWnd, &Prog, lpEnv); if (Prog.wStartFlags & START_DOSLAUNCH) SendMessage (hWnd, WM_COMMAND, IDD_RBDOS, MAKELPARAM (0, BN_CLICKED)); // Set window title SetTitle (hWnd); // Clear dirty flag fMainFlags &= ~MFLAG_DIRTY; } return 0; } //------------------------------------------------------------ // DoMainMenuSave - Process Save menu item //------------------------------------------------------------ LONG DoMainMenuSave (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { INT rc; if (lstrlen (szDataFileName) == 0) { PostMessage (hWnd, WM_COMMAND, IDM_SAVEAS, 0); return 0; } rc = SaveDataFile (hWnd, szDataFileName, &Prog, lpEnv); if (rc) PrintError (hWnd, rc); else { // Clear dirty flag fMainFlags &= ~MFLAG_DIRTY; // Set window title SetTitle (hWnd); } return 0; } //------------------------------------------------------------ // DoMainMenuSaveAs - Process Save As menu item //------------------------------------------------------------ LONG DoMainMenuSaveAs (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { INT i; char szStr[128], *pszStr; static char *szFilter[] = {"LaunchCtl Files", "*.LCD", "All Files (*.*)", "*.*", "" }; lstrcpy (szStr, szDataFileName); if (MyGetSavename (hWnd, szStr, sizeof (szStr), *szFilter, 1) == 0) return TRUE; if (lstrlen (szStr) == 0) return 0; // Append .LCD if no ext specified pszStr = szStr + lstrlen (szStr) - 1; for (i = 0; i < 4; i++) { if ((*pszStr == '.') || (*pszStr == '\\')) break; pszStr--; } if ((i == 4) || (*pszStr == '\\')) lstrcat (szStr, ".LCD"); lstrcpy (szDataFileName, szStr); PostMessage (hWnd, WM_COMMAND, IDM_SAVE, 0); return 0; } //------------------------------------------------------------ // DoMainCtlExit - Process Exit button //------------------------------------------------------------ LONG DoMainCtlExit (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { SendMessage (hWnd, WM_CLOSE, 0, 0); return 0; } //------------------------------------------------------------ // DoMainCtlAbout - Process About button //------------------------------------------------------------ LONG DoMainCtlAbout (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { MyDisplayDialog(hInst, "AboutBox", hWnd, (WNDPROC) AboutDlgProc, sVer); return 0; } //============================================================ // Control handling procedures for MainWindow //============================================================ //------------------------------------------------------------ // DoMainCtlRButtons - Process Radio buttons //------------------------------------------------------------ LONG DoMainCtlRButtons (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { INT i, sStart; HWND hCtl; if (wNotifyCode != BN_CLICKED) return FALSE; // // Perf default action for radio buttons // if ((idItem >= IDD_RBENV) && (idItem <= IDD_RBDOS)) { if (IsDlgButtonChecked (hWnd, idItem) == 1) return 0; CheckRadioButton (hWnd, IDD_RBENV, IDD_RBDOS, idItem); // Hide all type specific controls for (i = IDD_ENVA; i < IDD_DOSLAST+1; i++) { hCtl = GetDlgItem (hWnd, i); if (hCtl) ShowWindow (hCtl, SW_HIDE); } } // Now show proper controls switch (idItem) { case IDD_RBENV: sStart = IDD_ENVA; break; case IDD_RBSIZE: sStart = IDD_SIZEA; break; case IDD_RBDOS: sStart = IDD_DOSA; break; } for (i = sStart; i < sStart + 10; i++) { hCtl = GetDlgItem (hWnd, i); if (hCtl) ShowWindow (hCtl, SW_SHOW); } return 0; } //------------------------------------------------------------ // DoMainCtlRBStart - Process Start Radio buttons //------------------------------------------------------------ LONG DoMainCtlRBStart (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { if (wNotifyCode != BN_CLICKED) return FALSE; CheckRadioButton (hWnd, IDD_RF1, IDD_RF3, idItem); fMainFlags |= MFLAG_DIRTY; return TRUE; } //------------------------------------------------------------ // DoMainCtlRBEnv - Process Environment Radio buttons //------------------------------------------------------------ LONG DoMainCtlRBEnv (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { if (wNotifyCode != BN_CLICKED) return FALSE; CheckRadioButton (hWnd, IDD_ENVA, IDD_ENVB, idItem); fMainFlags |= MFLAG_DIRTY; return TRUE; } //------------------------------------------------------------ // DoMainCtlChkBoxes - Process CheckBoxes //------------------------------------------------------------ LONG DoMainCtlChkBoxes (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { INT i, sState; HWND hCtl; // // Perf default action for check boxes // if (((idItem == IDD_ENVA) || (idItem == IDD_SIZEA) || (idItem == IDD_DOSA)) && (wNotifyCode == BN_CLICKED)) { if (IsDlgButtonChecked (hWnd, idItem) == 1) sState = 0; else sState = 1; CheckDlgButton (hWnd, idItem, sState); // Enable/Disable associated ctls for (i = 2; i < 10; i++) if (hCtl = GetDlgItem (hWnd, idItem + i)) EnableWindow (hCtl, !sState); // If launching outside Windows, disable other options if (idItem == IDD_DOSA) { EnableWindow (GetDlgItem (hWnd, IDD_RBENV), !sState); EnableWindow (GetDlgItem (hWnd, IDD_RBSIZE), !sState); EnableWindow (GetDlgItem (hWnd, IDD_RF1), !sState); EnableWindow (GetDlgItem (hWnd, IDD_RF2), !sState); EnableWindow (GetDlgItem (hWnd, IDD_RF3), !sState); CheckRadioButton (hWnd, IDD_RBENV, IDD_RBDOS, IDD_RBDOS); } fMainFlags |= MFLAG_DIRTY; return TRUE; } return FALSE; } //------------------------------------------------------------ // DoMainCtlCmd - Process Command edit box //------------------------------------------------------------ LONG DoMainCtlCmd (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { if (wNotifyCode == EN_UPDATE) fMainFlags |= MFLAG_DIRTY; return TRUE; } //------------------------------------------------------------ // DoMainCtlEnvEdit - Process Edit Env button //------------------------------------------------------------ LONG DoMainCtlEnvEdit (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { HGLOBAL hEdit; // Edit icon selection hEdit = MyDisplayDialog(hInst, "AddEditBox", hWnd, (DLGPROC) EditEnvDlgProc, (LPARAM)lpEnv); if (hEdit) { GlobalUnlock (hEnv); GlobalFree (hEnv); hEnv = hEdit; lpEnv = GlobalLock (hEnv); FillLB (hWnd, IDD_ENVSPEC, lpEnv); fMainFlags |= MFLAG_DIRTY; } return 0; } //------------------------------------------------------------ // DoMainCtlBrowse - Process Browse button //------------------------------------------------------------ LONG DoMainCtlBrowse (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { char szStr[128], *pszStr; static char *szFilter[] = {"Programs", "*.EXE;*.COM;*.PIF;*.BAT", "All Files (*.*)", "*.*", "" }; if (MyGetFilename (hWnd, szStr, sizeof (szStr), *szFilter, 1) == 0) return TRUE; SetDlgItemText (hWnd, IDD_CMD, szStr); pszStr = strrchr (szStr, '\\'); if (pszStr) { *pszStr = '\0'; SetDlgItemText (hWnd, IDD_WDIR, szStr); } else SetDlgItemText (hWnd, IDD_WDIR, ""); PostMessage (hWnd, WM_COMMAND, IDD_DOSIBOX, 0); fMainFlags |= MFLAG_DIRTY; return 0; } //------------------------------------------------------------ // DoMainCtlSetIcon - Process SetIcon button //------------------------------------------------------------ LONG DoMainCtlSetIcon (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { HGLOBAL hEdit; LPMYPROGDATA lpProg; // Edit icon selection hEdit = MyDisplayDialog(hInst, "SetIconBox", hWnd, (DLGPROC) SetIconDlgProc, (LPARAM)(LPMYPROGDATA)&Prog); if (hEdit) { lpProg = (LPMYPROGDATA)GlobalLock (hEdit); lstrcpy (Prog.szIconFName, lpProg->szIconFName); Prog.wIconIndex = lpProg->wIconIndex; GlobalUnlock (hEdit); GlobalFree (hEdit); // Force icon set PostMessage (hWnd, WM_COMMAND, IDD_DOSIBOX, 0); fMainFlags |= MFLAG_DIRTY; } return 0; } //------------------------------------------------------------ // DoMainCtlDOSIBox - Process DOSIBox button //------------------------------------------------------------ LONG DoMainCtlDOSIBox (HWND hWnd, UINT idItem, HWND hwndCtl, UINT wNotifyCode) { HICON hIcon; // Delete old icon hIcon = (HICON)SendDlgItemMessage (hWnd, IDD_DOSICON, STM_GETICON, 0, 0); if (hIcon) DestroyIcon (hIcon); hIcon = 0; // Try getting icon from icon file otherwise, use exe GetDlgItemText (hWnd, IDD_CMD, Prog.szCmd, sizeof (Prog.szCmd)); GetDlgItemText (hWnd, IDD_WDIR, Prog.szDir, sizeof (Prog.szDir)); hIcon = GetBestIcon (&Prog, 0); if (hIcon < 2) hIcon = ExtractIcon (hInst, "ProgMan.EXE", Prog.wIconIndex); if (hIcon < 2) hIcon = ExtractIcon (hInst, "ProgMan.EXE", 1); if (hIcon > 1) SendDlgItemMessage (hWnd, IDD_DOSICON, STM_SETICON, hIcon, 0); return 0; } //============================================================ // EditEnvDlgProc - Edit Environment dialog box procedure //============================================================ BOOL CALLBACK EditEnvDlgProc (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) { FARPROC lp3dproc; LPSTR lpTmp; HGLOBAL hEdit; UINT wNotifyCode; char szTemp[256], ch; INT i, sLen; switch (wMsg) { case WM_INITDIALOG: // Use 3D fx if (h3DLib) { lp3dproc = GetProcAddress (h3DLib, "Ctl3dSubclassDlgEx"); if (lp3dproc) { (*lp3dproc) (hWnd, -1); } } // Fill in combo box with possible env vars SendDlgItemMessage (hWnd, IDD_NEWVAR, CB_LIMITTEXT, 255, 0); SendDlgItemMessage (hWnd, IDD_NEWVAR, CB_RESETCONTENT, 0, 0); lpTmp = lpDefEnv; while (*lpTmp) { SendDlgItemMessage (hWnd, IDD_NEWVAR, CB_ADDSTRING, 0, (LPARAM)lpTmp); lpTmp += lstrlen (lpTmp) + 1; } // Fill in list box with env vars if (lParam) FillLB (hWnd, IDD_LIST, (LPSTR)lParam); EnableWindow (GetDlgItem (hWnd, IDD_ENVADD), FALSE); EnableWindow (GetDlgItem (hWnd, IDD_ENVDEL), FALSE); return TRUE; case WM_COMMAND: wNotifyCode = HIWORD (lParam); switch (wParam) { case IDD_NEWVAR: if (wNotifyCode == CBN_SELCHANGE) { i = (INT) SendDlgItemMessage (hWnd, IDD_NEWVAR, CB_GETCURSEL, 0, 0); sLen = (INT)SendDlgItemMessage (hWnd, IDD_NEWVAR, CB_GETLBTEXT, i, (LPARAM)(LPSTR)szTemp); } else if (wNotifyCode == CBN_EDITUPDATE) sLen = GetDlgItemText (hWnd, IDD_NEWVAR, szTemp, sizeof (szTemp)); else break; // Search for valid env var assignment for (i = 0; (i < sLen) && (szTemp[i] != '='); i++); if ((i < sLen) && (szTemp[i+1] > ' ')) { i++; for (; (i < sLen) && (szTemp[i] != '='); i++); if (szTemp[i] != '=') { EnableWindow (GetDlgItem (hWnd, IDD_ENVADD), TRUE); break; } } EnableWindow (GetDlgItem (hWnd, IDD_ENVADD), FALSE); break; case IDD_ENVADD: sLen = (INT)GetDlgItemText (hWnd, IDD_NEWVAR, szTemp, sizeof (szTemp)); for (i = 0; (i < sLen) && (szTemp[i] != '='); i++); sLen = i+1; ch = szTemp[sLen]; szTemp[sLen] = '\0'; AnsiUpper (szTemp); i = (INT)SendDlgItemMessage (hWnd, IDD_LIST, LB_FINDSTRING, 0, (LPARAM)(LPSTR) szTemp); szTemp[sLen] = ch; if (i == LB_ERR) SendDlgItemMessage (hWnd, IDD_LIST, LB_ADDSTRING, 0, (LPARAM)(LPSTR) szTemp); else { SendDlgItemMessage (hWnd, IDD_LIST, LB_DELETESTRING, i, 0); SendDlgItemMessage (hWnd, IDD_LIST, LB_INSERTSTRING, i, (LPARAM)(LPSTR) szTemp); SendDlgItemMessage (hWnd, IDD_LIST, LB_SETCURSEL, i, 0); } break; case IDD_ENVDEL: i = (INT)SendDlgItemMessage (hWnd, IDD_LIST, LB_GETCURSEL, 0, 0); SendDlgItemMessage (hWnd, IDD_LIST, LB_DELETESTRING, i, 0); SendDlgItemMessage (hWnd, IDD_LIST, LB_SETCURSEL, max (i-1, 0), 0); break; case IDD_LIST: if (wNotifyCode == LBN_DBLCLK) { i = (INT)SendDlgItemMessage (hWnd, IDD_LIST, LB_GETCURSEL, 0, 0); SendDlgItemMessage (hWnd, IDD_LIST, LB_GETTEXT, i, (LPARAM)(LPSTR) szTemp); SetDlgItemText (hWnd, IDD_NEWVAR, szTemp); } else if (wNotifyCode == LBN_SELCHANGE) EnableWindow (GetDlgItem (hWnd, IDD_ENVDEL), TRUE); break; case IDOK: hEdit = GlobalAlloc (GHND, 0x10000); lpTmp = GlobalLock (hEdit); if (lpTmp) { for (i = 0; i < 16384; i++) { sLen = (INT)SendDlgItemMessage (hWnd, IDD_LIST, LB_GETTEXT, i, (LPARAM)lpTmp); if (sLen == LB_ERR) break; lpTmp += lstrlen (lpTmp) + 1; } *lpTmp = '\0'; GlobalUnlock (hEdit); } EndDialog(hWnd, hEdit); break; case IDCANCEL: EndDialog(hWnd, 0); break; } return TRUE; } return FALSE; } //============================================================ // SetIconDlgProc - SetIcon dialog box procedure //============================================================ BOOL CALLBACK SetIconDlgProc (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam) { static char *szFilter[] = {"Icon Files", "*.ICO;*.EXE;*.DLL", "All Files (*.*)", "*.*", "" }; FARPROC lp3dproc; char szStr[128]; LPMYPROGDATA lpProg; INT i, sCnt, sSel; HGLOBAL hEdit; HICON hIcon; RECT rect; OFSTRUCT of; switch (wMsg) { case WM_INITDIALOG: // Use 3D fx if (h3DLib) { lp3dproc = GetProcAddress (h3DLib, "Ctl3dSubclassDlgEx"); if (lp3dproc) { (*lp3dproc) (hWnd, -1); } } SendDlgItemMessage (hWnd, IDD_LIST, LB_SETCOLUMNWIDTH, GetSystemMetrics (SM_CXICON)+8, 0); // Fill in combo box with possible icon files SendDlgItemMessage (hWnd, IDD_ILIBS, CB_RESETCONTENT, 0, 0); sCnt = 0; for (i = 0; i < sIconLibCnt; i++) { sSel = OpenFile (IconLibs[i].szName, &of, OF_EXIST); if (sSel != HFILE_ERROR) { SendDlgItemMessage (hWnd, IDD_CMD, CB_ADDSTRING, 0, (LPARAM)(LPSTR)of.szPathName); sCnt++; } } if (lParam) { // See if program has an icon, if so, add it to the list lpProg = (LPMYPROGDATA) lParam; hIcon = GetBestIcon (lpProg, szStr); if (hIcon > 1) { DestroyIcon (hIcon); // Make sure icon file not already listed if (SendDlgItemMessage (hWnd, IDD_CMD, CB_FINDSTRING, -1, (LPARAM)(LPSTR)szStr) == CB_ERR) { AnsiUpper (szStr); SendDlgItemMessage (hWnd, IDD_CMD, CB_INSERTSTRING, 0, (LPARAM)(LPSTR)szStr); sCnt++; } } } // Scan icon files to see if matching icon index can be loaded. sSel = -1; for (i = 0; i < sCnt; i++) { SendDlgItemMessage (hWnd, IDD_CMD, CB_GETLBTEXT, i, (LPARAM)(LPSTR)szStr); hIcon = ExtractIcon (hInst, szStr, lpProg->wIconIndex); if (hIcon > 1) { SendDlgItemMessage (hWnd, IDD_CMD, CB_SETCURSEL, i, 0); sSel = lpProg->wIconIndex; DestroyIcon (hIcon); break; } } // if matching icon index not found, select first icon of any file if ((i == sCnt) && (lpProg->wIconIndex)) { lpProg->wIconIndex = 0; for (i = 0; i < sCnt; i++) { SendDlgItemMessage (hWnd, IDD_CMD, CB_GETLBTEXT, i, (LPARAM)(LPSTR)szStr); hIcon = ExtractIcon (hInst, szStr, lpProg->wIconIndex); if (hIcon > 1) { SendDlgItemMessage (hWnd, IDD_CMD, CB_SETCURSEL, i, 0); sSel = lpProg->wIconIndex; DestroyIcon (hIcon); break; } } } // Fill the icon listbox i = (INT)SendDlgItemMessage (hWnd, IDD_CMD, CB_GETCURSEL, 0, 0); SendDlgItemMessage (hWnd, IDD_CMD, CB_GETLBTEXT, i, (LPARAM)(LPSTR)szStr); sCnt = ModIconList (hWnd, szStr); if (sSel != -1) SendDlgItemMessage (hWnd, IDD_LIST, LB_SETCURSEL, sSel, 0); else if (sCnt) SendDlgItemMessage (hWnd, IDD_LIST, LB_SETCURSEL, 0, 0); // Set the size of the listbox to match the size of icons GetClientRect (GetDlgItem (hWnd, IDD_LIST), &rect); SetWindowPos (GetDlgItem (hWnd, IDD_LIST), NULL, 0, 0, rect.right - rect.left, GetSystemMetrics (SM_CYICON) + GetSystemMetrics (SM_CYHSCROLL) + 8, SWP_NOZORDER | SWP_NOMOVE); return TRUE; case WM_MEASUREITEM: ((LPMEASUREITEMSTRUCT)lParam)->itemWidth = GetSystemMetrics (SM_CXICON) + 8; ((LPMEASUREITEMSTRUCT)lParam)->itemHeight = GetSystemMetrics (SM_CYICON) + 8; return TRUE; case WM_DRAWITEM: { LPDRAWITEMSTRUCT di; HBRUSH hBrush; INT sOld; di = (LPDRAWITEMSTRUCT)lParam; if (di->itemState & ODS_SELECTED) { hBrush = CreateSolidBrush (GetSysColor (COLOR_HIGHLIGHT)); } else { hBrush = CreateSolidBrush (GetSysColor (COLOR_WINDOW)); } FillRect (di->hDC, &di->rcItem, hBrush); DeleteObject (hBrush); sOld = SetMapMode (di->hDC, MM_TEXT); i = DrawIcon (di->hDC, di->rcItem.left+4, di->rcItem.top+4, (HICON)di->itemData); SetMapMode (di->hDC, sOld); } return TRUE; case WM_COMMAND: switch (wParam) { case IDD_CMD: if (HIWORD (lParam) == CBN_EDITUPDATE) { SendDlgItemMessage (hWnd, IDD_CMD, WM_GETTEXT, sizeof (szStr), (LPARAM)(LPSTR)szStr); // Fill the icon listbox sCnt = ModIconList (hWnd, szStr); SendDlgItemMessage (hWnd, IDD_LIST, LB_SETCURSEL, 0, 0); } else if (HIWORD (lParam) == CBN_SELCHANGE) { i = (INT)SendDlgItemMessage (hWnd, IDD_CMD, CB_GETCURSEL, 0, 0); SendDlgItemMessage (hWnd, IDD_CMD, CB_GETLBTEXT, i, (LPARAM)(LPSTR)szStr); // Fill the icon listbox sCnt = ModIconList (hWnd, szStr); SendDlgItemMessage (hWnd, IDD_LIST, LB_SETCURSEL, 0, 0); } break; case IDD_LIST: if (HIWORD (lParam) != LBN_DBLCLK) break; PostMessage (hWnd, WM_COMMAND, IDOK, MAKELPARAM (0, BN_CLICKED)); break; case IDD_BROWSE: if (MyGetFilename (hWnd, szStr, sizeof (szStr), *szFilter, 1) == 0) break; // Make sure icon file not already listed i = (INT) SendDlgItemMessage (hWnd, IDD_CMD, CB_FINDSTRING, -1, (LPARAM)(LPSTR)szStr); if (i == CB_ERR) { AnsiUpper (szStr); i = (INT)SendDlgItemMessage (hWnd, IDD_CMD, CB_INSERTSTRING, 0, (LPARAM)(LPSTR)szStr); } SendDlgItemMessage (hWnd, IDD_CMD, CB_SETCURSEL, i, 0); PostMessage (hWnd, WM_COMMAND, IDD_CMD, MAKELPARAM (0,CBN_SELCHANGE)); break; case IDOK: hEdit = GlobalAlloc (GHND, sizeof (MYPROGDATA)); lpProg = (LPMYPROGDATA)GlobalLock (hEdit); //Get and validate the working directory GetDlgItemText (hWnd, IDD_CMD, lpProg->szIconFName, sizeof (lpProg->szIconFName)); // Get hot key lpProg->wIconIndex = (UINT)SendDlgItemMessage (hWnd, IDD_LIST, LB_GETCURSEL, 0, 0); if (lpProg->wIconIndex == LB_ERR) lpProg->wIconIndex = 0; GlobalUnlock (hEdit); // Delete icons from listbox ModIconList (hWnd, 0); EndDialog(hWnd, hEdit); break; case IDCANCEL: ModIconList (hWnd, 0); EndDialog(hWnd, 0); break; } return TRUE; } return FALSE; } //------------------------------------------------------------ // GetEndofName - returns a pointer to the end of a filename //------------------------------------------------------------ LPSTR GetEndofName (LPSTR lpName) { char ch; while (*lpName) { ch = *lpName; if ((strchr (":\\.!#$%^&()-_{}~", ch) == 0) && !IsCharAlphaNumeric (*lpName)) break; lpName++; } return lpName; } //------------------------------------------------------------ // Get best icon, returns an icon from icon file or program. //------------------------------------------------------------ HICON GetBestIcon (LPMYPROGDATA lpProg, LPSTR lpName) { HICON hIcon; LPSTR lpFound; HINSTANCE hTest; char szStr[128]; char szResults[128]; lstrcpy (szStr, lpProg->szCmd); *GetEndofName (szStr) = '\0'; hIcon = ExtractIcon (hInst, szStr, lpProg->wIconIndex); if (hIcon < 2) hIcon = ExtractIcon (hInst, szStr, 0); if (hIcon < 2) hIcon = ExtractIcon (hInst, lpProg->szIconFName, lpProg->wIconIndex); // If no icon file, try program name if (hIcon < 2) { hTest = FindExecutable (szStr, lpProg->szDir, szResults); hIcon = ExtractIcon (hInst, szResults, lpProg->wIconIndex); if (lpName) lpFound = szResults; } else lpFound = lpProg->szIconFName; if (lpName) lstrcpy (lpName, lpFound); return hIcon; } //------------------------------------------------------------ // ModIconList - Empty and fill icon listbox //------------------------------------------------------------ INT ModIconList (HWND hWnd, LPSTR szFile) { INT i, sCnt; HICON hIcon; HCURSOR hCursor; sCnt = (INT)SendDlgItemMessage (hWnd, IDD_LIST, LB_GETCOUNT, 0, 0); for (i = 0; i < sCnt; i++) { hIcon = (HICON)SendDlgItemMessage (hWnd, IDD_LIST, LB_GETITEMDATA, i, 0); DestroyIcon (hIcon); } SendDlgItemMessage (hWnd, IDD_LIST, LB_RESETCONTENT, 0, 0); sCnt = 0; if (szFile) { hCursor = SetCursor (LoadCursor (NULL, IDC_WAIT)); hIcon = 2; for (i = 0; i < 256, hIcon > 1; i++) { hIcon = ExtractIcon (hInst, szFile, i); if (hIcon > 1) { SendDlgItemMessage (hWnd, IDD_LIST, LB_INSERTSTRING, i, (LPARAM)hIcon); sCnt++; } } SetCursor (hCursor); } SendDlgItemMessage (hWnd, IDD_LIST, WM_SETREDRAW, 1, 0); return sCnt; } //============================================================ // AboutDlgProc - About dialog box dialog procedure //============================================================ BOOL CALLBACK AboutDlgProc (HWND hWnd, UINT msg, UINT wParam, LONG lParam) { char szAboutStr[128]; HWND hwndText; RECT rect; HDC hdc; PAINTSTRUCT ps; HPEN hDPen, hLPen, hOldPen; switch (msg) { case WM_INITDIALOG: GetDlgItemText (hWnd, IDD_PROGSTR, szAboutStr, sizeof (szAboutStr)); itoa ((INT)lParam/10, &szAboutStr[strlen (szAboutStr)], 10); strcat (szAboutStr, "."); itoa ((INT)lParam%10, &szAboutStr[strlen (szAboutStr)], 10); SetDlgItemText (hWnd, IDD_PROGSTR, szAboutStr); return TRUE; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); hwndText = GetDlgItem (hWnd, IDD_COPYDATE); if (IsWindow (hwndText)) { GetClientRect (hwndText, &rect); ClientToScreen (hwndText, (LPPOINT)&rect); ScreenToClient (hWnd, (LPPOINT)&rect); rect.left -= 2; rect.top -= 2; rect.right += rect.left + 4; rect.bottom += rect.top + 4; hDPen = CreatePen (PS_SOLID, 1, GetSysColor (COLOR_BTNSHADOW)); hLPen = CreatePen (PS_SOLID, 1, GetSysColor (COLOR_BTNHIGHLIGHT)); hOldPen = SelectObject (hdc, hDPen); MoveTo (hdc, rect.left, rect.bottom); LineTo (hdc, rect.left, rect.top); LineTo (hdc, rect.right+1, rect.top); //Start at bottom left, draw light pen over and up. SelectObject (hdc, hLPen); MoveTo (hdc, rect.left+1, rect.bottom); LineTo (hdc, rect.right, rect.bottom); LineTo (hdc, rect.right, rect.top); SelectObject (hdc, hOldPen); DeleteObject (hDPen); DeleteObject (hLPen); } EndPaint(hWnd, &ps); return TRUE; case WM_COMMAND: if ((wParam == IDOK) || (wParam == IDCANCEL)) { EndDialog(hWnd, 0); return TRUE; } } return FALSE; } //------------------------------------------------------------ // SetControls - Sets the controls on the main window //------------------------------------------------------------ INT SetControls (HWND hWnd, LPMYPROGDATA lpProg, LPSTR lpEnvBlk) { INT i, rc = 0; SetDlgItemText (hWnd, IDD_CMD, lpProg->szCmd); SetDlgItemText (hWnd, IDD_WDIR, lpProg->szDir); SetDlgItemText (hWnd, IDD_DOSSPEC, lpProg->szDesc); if (lpProg->wStartFlags & START_MIN) i = IDD_RF2; else if (lpProg->wStartFlags & START_MAX) i = IDD_RF3; else i = IDD_RF1; CheckRadioButton (hWnd, IDD_RF1, IDD_RF3, i); i = IDD_ENVB; if (lpProg->wStartFlags & START_DEFENV) i = IDD_ENVA; CheckRadioButton (hWnd, IDD_ENVA, IDD_ENVB, i); // If depending on def size checkbox, enable/disable // size ctls by simulating chkbox click. if (((IsDlgButtonChecked (hWnd, IDD_SIZEA)) && !(lpProg->wStartFlags & START_DEFSIZE)) || ((!IsDlgButtonChecked (hWnd, IDD_SIZEA)) && (lpProg->wStartFlags & START_DEFSIZE))) SendMessage (hWnd, WM_COMMAND, IDD_SIZEA, MAKELPARAM (0, BN_CLICKED)); // If depending on outside Windows checkbox, // enable/disable size ctls by simulating // chkbox click. if (((IsDlgButtonChecked (hWnd, IDD_DOSA)) && !(lpProg->wStartFlags & START_DOSLAUNCH)) || ((!IsDlgButtonChecked (hWnd, IDD_DOSA)) && (lpProg->wStartFlags & START_DOSLAUNCH))) SendMessage (hWnd, WM_COMMAND, IDD_DOSA, MAKELPARAM (0, BN_CLICKED)); FillLB (hWnd, IDD_ENVSPEC, lpEnvBlk); SetDlgItemInt (hWnd, IDD_SIZEX, lpProg->rect.left, TRUE); SetDlgItemInt (hWnd, IDD_SIZEY, lpProg->rect.top, TRUE); SetDlgItemInt (hWnd, IDD_SIZECX, lpProg->rect.right, TRUE); SetDlgItemInt (hWnd, IDD_SIZECY, lpProg->rect.bottom, TRUE); SendMessage (hWnd, WM_COMMAND, IDD_DOSIBOX, 0); SendMessage (hWnd, WM_COMMAND, IDD_RBENV, MAKELPARAM (0, BN_CLICKED)); // Reset dirty flag set by SetControls fMainFlags &= ~MFLAG_DIRTY; return 0; } //------------------------------------------------------------ // OpenDataFile - Reads a data file //------------------------------------------------------------ INT OpenDataFile (LPSTR szIn, LPMYPROGDATA lpProg, LPSTR lpEnvBlk) { OFSTRUCT of; HFILE hFile; INT i, rc = 0; UINT wLen = 0; char szTemp[128]; if (lstrlen (szIn)) { hFile = OpenFile (szIn, &of, OF_READ | OF_SHARE_EXCLUSIVE); if (hFile != HFILE_ERROR) { // Read identifer tag _lread (hFile, szTemp, strlen (szFileTag) + 1); if (lstrcmp (szTemp, szFileTag)) { _lclose (hFile); return ERR_BADFILE; } // Get program data; i = _lread (hFile, lpProg, sizeof (MYPROGDATA)); if (i == sizeof (MYPROGDATA)) { _lread (hFile, &wLen, sizeof (UINT)); _lread (hFile, lpEnvBlk, wLen); lstrcpy (szDataFileName, of.szPathName); _lclose (hFile); } else rc = ERR_BADFILE; } else rc = ERR_DOS + of.nErrCode; } else rc = ERR_BADFILE; return rc; } //------------------------------------------------------------ // SaveDataFile - Writes the data to the data file. //------------------------------------------------------------ INT SaveDataFile (HWND hWnd, LPSTR szOut, LPMYPROGDATA lpProg, LPSTR lpEnvBlk) { OFSTRUCT of; HFILE hFile; LPSTR lpTmp; INT i, rc = 0; UINT wLen = 0; char szTemp[128], szStr[128]; //Get and validate the working directory GetDlgItemText (hWnd, IDD_WDIR, lpProg->szDir, sizeof (lpProg->szDir)); if (lstrlen (lpProg->szDir) != 0) { lstrcpy (szTemp, lpProg->szDir); getcwd (szStr, sizeof (szStr)); i = chdir (szTemp); chdir (szStr); if (i != 0) { lstrcpy (szStr, "Can not locate the working directory:\n\n"); lstrcat (szStr, lpProg->szDir); lstrcat (szStr, "\n\nShould this directory be used anyway?"); i = MessageBox (hWnd, szStr, szAppName, MB_ICONEXCLAMATION | MB_YESNO); if (i != IDYES) return TRUE; } } //Get and validate the command line GetDlgItemText (hWnd, IDD_CMD, lpProg->szCmd, sizeof (lpProg->szCmd)); if (lstrlen (lpProg->szCmd) == 0) rc = ERR_NOCMDSPECIFIED; else { // Verify that program exists // Find end of file name lpTmp = GetEndofName (lpProg->szCmd); *lpTmp = '\0'; // Call Shell.dll to get association i = (INT)FindExecutable (lpProg->szCmd, lpProg->szDir, szStr); if (i <= 32) rc = i + ERR_LAUNCH; else GetDlgItemText (hWnd, IDD_CMD, lpProg->szCmd, sizeof (lpProg->szCmd)); } GetDlgItemText (hWnd, IDD_DOSSPEC, lpProg->szDesc, sizeof (lpProg->szDesc)); // Get startup flags lpProg->wStartFlags &= ~(START_MIN | START_MAX | START_DEFENV | START_DEFSIZE | START_DOSLAUNCH); if (IsDlgButtonChecked (hWnd, IDD_RF2)) lpProg->wStartFlags |= START_MIN; else if (IsDlgButtonChecked (hWnd, IDD_RF3)) lpProg->wStartFlags |= START_MAX; if (IsDlgButtonChecked (hWnd, IDD_ENVA)) lpProg->wStartFlags |= START_DEFENV; if (IsDlgButtonChecked (hWnd, IDD_SIZEA)) lpProg->wStartFlags |= START_DEFSIZE; if (IsDlgButtonChecked (hWnd, IDD_DOSA)) lpProg->wStartFlags |= START_DOSLAUNCH; lpProg->rect.left = GetDlgItemInt (hWnd, IDD_SIZEX, &i, TRUE); if (lpProg->rect.left < -1) i = 0; if (i) lpProg->rect.top = GetDlgItemInt (hWnd, IDD_SIZEY, &i, TRUE); if (lpProg->rect.top < -1) i = 0; if (i) lpProg->rect.right = GetDlgItemInt (hWnd, IDD_SIZECX, &i, TRUE); if (lpProg->rect.right < -1) i = 0; if (i) lpProg->rect.bottom = GetDlgItemInt (hWnd, IDD_SIZECY, &i, TRUE); if (lpProg->rect.bottom < -1) i = 0; if (!i) rc = ERR_BADNUM; // // Write data to disk // if (rc == 0) { hFile = OpenFile (szOut, &of, OF_CREATE | OF_READWRITE | OF_SHARE_EXCLUSIVE); if (hFile != HFILE_ERROR) { rc = 0; // Write identifer tag for file and write _lwrite (hFile, szFileTag, lstrlen (szFileTag) + 1); // Write status flags _lwrite (hFile, lpProg, sizeof (MYPROGDATA)); lpTmp = lpEnvBlk; while (*lpTmp) { i = lstrlen (lpTmp) + 1; wLen += (UINT)i; lpTmp += i; } wLen++; _lwrite (hFile, &wLen, sizeof (UINT)); _lwrite (hFile, lpEnvBlk, wLen); _lclose (hFile); } else rc = ERR_DOS + of.nErrCode; } return rc; } //------------------------------------------------------------ // FillLB - Fill listbox //------------------------------------------------------------ INT FillLB (HWND hWnd, UINT wID, LPSTR lpTmp) { SendDlgItemMessage (hWnd, wID, LB_RESETCONTENT, 0, 0); while (*lpTmp) { SendDlgItemMessage (hWnd, wID, LB_ADDSTRING, 0, (LPARAM)lpTmp); lpTmp += lstrlen (lpTmp) + 1; } return 0; } //============================================================ // General Helper Routines //============================================================ //------------------------------------------------------------ // PrintError - Displays a message box with an error code //------------------------------------------------------------ void PrintError (HWND hWnd, INT rc) { char szErrStr[80]; rc = abs (rc); if (LoadString (hInst, rc, szErrStr, sizeof (szErrStr)) == 0) { wsprintf (szErrStr, "Error number: %d", rc); } MessageBox (hWnd, szErrStr, szTitleText, MB_OK | MB_ICONHAND); return; } //------------------------------------------------------------ // MyDisplayDialog - Display a dialog box //------------------------------------------------------------ INT MyDisplayDialog (HINSTANCE hInstance, LPCSTR szDlgName, HWND hWnd, WNDPROC lpDialogProc, LPARAM lParam) { WNDPROC lpDlgProcInst; INT rc; lpDlgProcInst = MakeProcInstance(lpDialogProc, hInst); rc = DialogBoxParam (hInstance, szDlgName, hWnd, lpDlgProcInst, lParam); FreeProcInstance(lpDlgProcInst); return rc; } //------------------------------------------------------------ // MyWritePrivateProfileInt - Writes an integer to the profile //------------------------------------------------------------ BOOL MyWritePrivateProfileInt (char *szSec, char *szEntry, int Num, int Base, char *szProfile) { char szStr[33]; itoa (Num, szStr, Base); return WritePrivateProfileString (szSec, szEntry, szStr, szProfile); } //------------------------------------------------------------ // MyGetFilename - Uses the common File Open dialog box to // query the user for a filename //------------------------------------------------------------ BOOL MyGetFilename (HWND hWnd, char *szFilename, INT sMaxLen, char *szFilter, INT sFilterIndex) { OPENFILENAME ofn; *szFilename = '\0'; ofn.lStructSize = sizeof (OPENFILENAME); ofn.hwndOwner = hWnd; ofn.hInstance = hInst; ofn.lpstrFilter = szFilter; ofn.lpstrCustomFilter = 0; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = sFilterIndex; ofn.lpstrFile = szFilename; ofn.nMaxFile = sMaxLen; ofn.lpstrFileTitle = 0; ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = 0; ofn.lpstrTitle = 0; ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST; ofn.nFileOffset = 0; ofn.nFileExtension = 0; ofn.lpstrDefExt = "LCD"; ofn.lCustData = 0; ofn.lpfnHook = 0; ofn.lpTemplateName = 0; return (GetOpenFileName (&ofn)); } //------------------------------------------------------------ // MyGetSavename - Uses the common Save dialog box to // query the user for a filename //------------------------------------------------------------ BOOL MyGetSavename (HWND hWnd, char *szFilename, INT sMaxLen, char *szFilter, INT sFilterIndex) { OPENFILENAME ofn; memset (&ofn, 0, sizeof (ofn)); ofn.lStructSize = sizeof (ofn); ofn.hwndOwner = hWnd; ofn.hInstance = hInst; ofn.lpstrFilter = szFilter; ofn.nFilterIndex = sFilterIndex; ofn.lpstrFile = szFilename; ofn.nMaxFile = sMaxLen; ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; return (GetSaveFileName (&ofn)); } //------------------------------------------------------------ // MySubClassWindow - Subclasses a window //------------------------------------------------------------ WNDPROC MySubClassWindow (HWND hWnd, WNDPROC lpfnNewProc) { WNDPROC lpfnOldProc; lpfnOldProc = (WNDPROC) GetWindowLong (hWnd, GWL_WNDPROC); SetWindowLong (hWnd, GWL_WNDPROC, (LONG) lpfnNewProc); return lpfnOldProc; }