/* * DeskSave.c v2.0 15 Sep 1988 * v2.0a 20 Jul 1990 * * Windows 3.0 Desk Saving Utility * * Written by Jari Salminen, OH2BYQ * UUCP: mcvax!tut!kolvi!jsa * Internet: jsa@kolvi.hut.FI * * Usage: * To save desk: * - run DESKSAVE * - select command "Save Desk" from System menu * * To arrange desk: * - run DESKSAVE and select command "Arrange Desk" * or * - run DESKSAVE with command line option "-l" * or * - add DESKLOAD.EXE to "Load"-list in WIN.INI as the last name in list * ( done by DESKSAVE with "Save Desk" command ) * * This file creates both DESKSAVE.OBJ and DESKLOAD.OBJ * For DESKLOAD.OBJ compile with option /DDESKLOAD * */ #define NOMINMAX #include #include #include #include "desksave.h" #define MAXINT 32767 #define MAX_WIN 64 /* Max. number of windows that */ /* can be arranged */ #define MAX_LIST_SIZE 1024 /* Menu command definitions */ #define CMD_SAVEDESK 1 #define CMD_ARRDESK 2 #define CMD_CLEAR 3 #define CMD_ABOUT 4 HANDLE hInstance; /* Our instance handle */ HWND hWndDeskSave; /* hWnd of our icon */ FARPROC lpEnumWndProc; /* Enumerate windows */ char szLoadList[MAX_LIST_SIZE]; /* List of files to load */ char szRunList[MAX_LIST_SIZE]; /* List of files to run */ char szFileName[_MAX_FNAME + _MAX_EXT]; /* Name of file */ char szFileNameKey[_MAX_FNAME + _MAX_EXT + 1]; char szKeyList[MAX_LIST_SIZE]; /* List of coordinates for file */ char szNameList[2 * MAX_LIST_SIZE]; /* List of file handeled */ BOOL bSaveFlag; BOOL bInitialMSDOS; char szClass[] = "DeskSave"; /* Our window class name */ char szTitle[] = "DeskSave"; /* Our window title */ char szSaveDesk[] = "Save &Desk"; char szArrDesk[] = "&Arrange Desk"; char szClrRun[] = "C&lear \"Load\" and \"Run\""; char szAbout[] = "A&bout DeskSave..."; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ BOOL IsRunable( HWND ); BOOL IsLoadable( HWND ); long FAR PASCAL DeskSaveWndProc( HWND, unsigned, WORD, LONG ); BOOL ArrangeWindow( HWND ); int PASCAL WinMain( HANDLE, HANDLE, LPSTR, int ); BOOL Initialize( void ); BOOL FAR PASCAL AboutBox( HWND, unsigned, WORD, LONG ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* DeskSave's window function. */ long FAR PASCAL DeskSaveWndProc( hWnd, wMsg, wParam, lParam ) HWND hWnd; /* Window handle */ unsigned wMsg; /* Message number */ WORD wParam; /* Word parameter for the message */ LONG lParam; /* Long parameter for the message */ { FARPROC lpProc; /* ProcInstance for AboutBox */ switch( wMsg ) { /* Destroy-window message - time to quit the application */ case WM_DESTROY: PostQuitMessage( 0 ); return(0L); /* Query open icon message - don't allow icon to be opened! */ case WM_QUERYOPEN: return(0L); /* System menu command message - process the command if ours */ case WM_SYSCOMMAND: switch( wParam ) { case CMD_SAVEDESK: SaveDesk(); return(0L); case CMD_ARRDESK: ArrangeDesk(); return(0L); case CMD_CLEAR: WriteProfileString((LPSTR)"windows",(LPSTR)"Run", (LPSTR)"" ); WriteProfileString((LPSTR)"windows",(LPSTR)"Load", (LPSTR)"" ); return(0L); case CMD_ABOUT: lpProc = MakeProcInstance( (FARPROC)AboutBox, hInstance ); if( ! lpProc ) return(0L); DialogBox( hInstance, MAKEINTRESOURCE(ABOUTBOX), hWnd, lpProc ); FreeProcInstance( lpProc ); return(0L); } break; } /* For all other messages, we pass them on to DefWindowProc */ return( DefWindowProc( hWnd, wMsg, wParam, lParam )); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ BOOL FAR PASCAL EnumWndProc( hWnd, lParam ) HWND hWnd; LONG lParam; { MSG Msg; if ( bSaveFlag ) { SaveWindow( hWnd ); } else { ArrangeWindow( hWnd ); } #ifdef DESKLOAD /* Yield control to other applications !!! * It slows this applications down so that MS-WINDOWS * initial MSDOS.EXE is shown up and DeskLoad can destroy it ! */ PeekMessage( (LPMSG)&Msg, hWndDeskSave, 0, 0, PM_NOREMOVE ); #endif return(TRUE); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ArrangeDesk() { strcpy( szNameList, "" ); bInitialMSDOS = FALSE; bSaveFlag = FALSE; EnumWindows( lpEnumWndProc, 0L ); } ArrangeWindow( hWnd ) HWND hWnd; { RECT r; char s[40], *sp; int i, nc; if ( !IsRunable( hWnd ) && !IsIconic( hWnd )) return(FALSE); GetFileName( hWnd ); /* Check DESKSAVE and WIN*.OVL */ switch ( NameOK() ) { case 0: /* OK */ break; case 1: /* DESKSAVE */ return(1); case 2: /* WIN*.OVL == MSDOS.EXE */ strcpy( szFileName, "MSDOS.EXE" ); #ifdef DESKLOAD /* Is this first iconic MSDOS.EXE ? If so, kill that window */ if ( !bInitialMSDOS && IsIconic( hWnd ) ) { bInitialMSDOS = TRUE; PostMessage( hWnd, WM_SYSCOMMAND, SC_CLOSE, 0L ); return(1); } #endif break; } /* Keyname for iconic applications begins with 'i' */ if ( IsIconic( hWnd ) ) { strcpy( szFileNameKey, "i" ); strcat( szFileNameKey, szFileName ); } else { strcpy( szFileNameKey, szFileName ); } if ( GetProfileString( (LPSTR)szTitle, (LPSTR)szFileNameKey, (LPSTR)"", (LPSTR)szKeyList, MAX_LIST_SIZE ) == 0 ) return(NULL); /* Has this file been placed before ? */ nc = GetNameCount( szFileNameKey ); sp = szKeyList; for( i=0 ; i < nc; i++ ) { /* Search right coordinates */ char *sp2; if ((sp2=strchr( sp, ';' )) == NULL) return(NULL); sp = ++sp2; } if (sscanf( sp, "%d %d %d %d", &r.left, &r.top, &r.right, &r.bottom ) != 4) return(NULL); /* Name and coordinates found. Add name to list */ strcat( szNameList, szFileNameKey ); strcat( szNameList, " " ); /* Move window to its position */ SetWindowPos( hWnd, (HWND)NULL, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOACTIVATE | SWP_NOZORDER ); return(NULL); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* These functions save the positions of the windows. */ SaveDesk() { HWND hWnd = NULL; strcpy( szLoadList, "" ); strcpy( szRunList, "" ); bSaveFlag = TRUE; EnumWindows( lpEnumWndProc, 0L ); /* Add loader program to the last of the LOADLIST !*/ strcat( szLoadList, "DESKLOAD.EXE" ); WriteProfileString((LPSTR)"windows",(LPSTR)"Run", (LPSTR)szRunList ); WriteProfileString((LPSTR)"windows",(LPSTR)"Load",(LPSTR)szLoadList ); } SaveWindow( hWnd ) HWND hWnd; { if( IsRunable( hWnd ) ) { AddRunList( hWnd ); return(NULL); } if( IsLoadable( hWnd ) ) { AddLoadList( hWnd ); return(NULL); } } AddRunList( hWnd ) HWND hWnd; { RECT rc; char s[40]; GetFileName( hWnd ); /* Check DESKSAVE and WIN*.OVL */ switch ( NameOK() ) { case 0: /* OK */ break; case 1: /* DESKSAVE */ return(NULL); case 2: /* WIN*.OVL == MSDOS.EXE */ strcpy( szFileName, "MSDOS.EXE" ); break; } GetWindowRect( hWnd, (LPRECT)&rc ); if (strstr( szRunList, szFileName ) != NULL) { if ( GetProfileString( (LPSTR)szTitle, (LPSTR)szFileName, (LPSTR)"", (LPSTR)szKeyList, MAX_LIST_SIZE - 30 ) == 0 ) { return(FALSE); } sprintf( s, ";%d %d %d %d", rc.left, rc.top, rc.right, rc.bottom); strcat( szKeyList, s ); } else { sprintf( szKeyList, "%d %d %d %d", rc.left, rc.top, rc.right, rc.bottom); } WriteProfileString( (LPSTR)szTitle, (LPSTR)szFileName, (LPSTR)szKeyList ); strcat( szRunList, szFileName ); strcat( szRunList, " " ); } AddLoadList( hWnd ) HWND hWnd; { RECT rc; char s[40]; GetFileName( hWnd ); strcpy( szFileNameKey, "i" ); strcat( szFileNameKey, szFileName ); /* Check DESKSAVE and WIN*.OVL */ switch ( NameOK() ) { case 0: /* OK */ break; case 1: /* DESKSAVE */ return(NULL); case 2: /* WIN*.OVL == MSDOS.EXE */ strcpy( szFileNameKey, "iMSDOS.EXE" ); strcpy( szFileName, "MSDOS.EXE" ); break; } GetWindowRect( hWnd, (LPRECT)&rc ); if (strstr( szLoadList, szFileName ) != NULL) { if ( GetProfileString( (LPSTR)szTitle, (LPSTR)szFileNameKey, (LPSTR)"", (LPSTR)szKeyList, MAX_LIST_SIZE - 30 ) == 0 ) { return(FALSE); } sprintf( s, ";%d %d %d %d", rc.left, rc.top, rc.right, rc.bottom); strcat( szKeyList, s ); } else { sprintf( szKeyList, "%d %d %d %d", rc.left, rc.top, rc.right, rc.bottom); } WriteProfileString( (LPSTR)szTitle, (LPSTR)szFileNameKey, (LPSTR)szKeyList ); strcat( szLoadList, szFileName ); strcat( szLoadList, " " ); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* Tells whether a window can be run, returns TRUE if so. * We will run only top level, resizable windows that are not * minimized and not maximized. */ BOOL IsRunable( hWnd ) HWND hWnd; { DWORD dwStyle; dwStyle = GetWindowLong( hWnd, GWL_STYLE ); return( ! ( dwStyle & ( WS_POPUP | WS_MINIMIZE | WS_MAXIMIZE ) ) && ( dwStyle & WS_VISIBLE ) ); } /* Tells whether a window can be load, returns TRUE if so. * We will load only minimized windows. */ BOOL IsLoadable( hWnd ) HWND hWnd; { DWORD dwStyle; dwStyle = GetWindowLong( hWnd, GWL_STYLE ); return( ( dwStyle & WS_MINIMIZE ) && ( dwStyle & WS_VISIBLE ) ); } GetFileName( hWnd ) HWND hWnd; { HANDLE hInst; char s[_MAX_PATH]; static char drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME], ext[_MAX_EXT]; hInst = GetWindowWord( hWnd, GWW_HINSTANCE ); GetModuleFileName( hInst, (LPSTR)s, _MAX_PATH ); _splitpath( s, drive, dir, fname, ext ); strcpy( szFileName, fname ); strcat( szFileName, ext ); } NameOK() { /* Don't save DESKSAVE to list */ if ( strnicmp( szFileName, szTitle, strlen(szTitle) ) == 0 ) return 1; /* Don't save WIN*.OVL */ if ( strnicmp( szFileName, "WIN", 3 ) == 0 && strnicmp( &szFileName[ strlen(szFileName) - 3], "OVL", 3) == 0 ) return 2; return 0; } /* Count occurrences of string s in szNamelist */ GetNameCount( s ) char *s; { int i; char *spNames, *sp; i = 0; spNames = szNameList; while( (sp=strstr( spNames, s )) != NULL ) { spNames = ( sp + strlen( s ) ); i++; } return i; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* Application main program. */ int PASCAL WinMain( hInst, hPrevInst, lpszCmdLine, nCmdShow ) HANDLE hInst; /* Our instance handle */ HANDLE hPrevInst; /* Previous instance of this application */ LPSTR lpszCmdLine; /* Pointer to any command line params */ int nCmdShow; /* Parameter to use for first ShowWindow */ { MSG msg; /* Message structure */ /* Allow only a single instance */ if( hPrevInst ) { MessageBeep( 0 ); return 0; } /* Save our instance handle in static variable */ hInstance = hInst; /* Initialize application, quit if any errors */ if( ! Initialize() ) return FALSE; #ifdef DESKLOAD ArrangeDesk(); return 0; #else /* If parameter "-l" arrange desk */ if (lpszCmdLine[0] == '-' && lpszCmdLine[1] == 'l') { ArrangeDesk(); } /* Main message processing loop */ while( GetMessage( &msg, NULL, 0, 0 ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } return msg.wParam; #endif } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* Initialize DESKSAVE. Assumes a single instance. * Returns TRUE if initialization succeeded, FALSE if failed. */ BOOL Initialize() { WNDCLASS Class; /* Class structure for RegisterClass */ HMENU hMenu; /* Menu handle of system menu */ /* Register our window class */ Class.style = 0; Class.cbClsExtra = 0; Class.cbWndExtra = 0; Class.lpfnWndProc = DeskSaveWndProc; Class.hInstance = hInstance; Class.hIcon = LoadIcon( hInstance, szClass ); Class.hCursor = LoadCursor( NULL, IDC_ARROW ); Class.hbrBackground = COLOR_WINDOW + 1; Class.lpszMenuName = NULL; Class.lpszClassName = szClass; if( ! RegisterClass( &Class ) ) return FALSE; /* Create our window but don't iconize it yet */ hWndDeskSave = CreateWindow( szClass, szTitle, WS_OVERLAPPED | WS_SYSMENU, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL ); if( ! hWndDeskSave ) return FALSE; lpEnumWndProc = MakeProcInstance( (FARPROC)EnumWndProc, hInstance ); #ifndef DESKLOAD /* Add our menu items to the System (Control) menu, at the top of * the menu, so "Tile Columns" becomes the default choice */ hMenu = GetSystemMenu( hWndDeskSave, FALSE ); ChangeMenu( hMenu, 0, NULL, MAXINT, MF_APPEND | MF_SEPARATOR ); ChangeMenu( hMenu, 0, szSaveDesk, CMD_SAVEDESK, MF_APPEND ); ChangeMenu( hMenu, 0, szArrDesk, CMD_ARRDESK, MF_APPEND ); ChangeMenu( hMenu, 0, szClrRun, CMD_CLEAR, MF_APPEND ); ChangeMenu( hMenu, 0, NULL, MAXINT, MF_APPEND | MF_SEPARATOR ); ChangeMenu( hMenu, 0, szAbout, CMD_ABOUT, MF_APPEND ); /* Now display our window as an icon */ ShowWindow( hWndDeskSave, SW_SHOWMINIMIZED ); #endif return TRUE; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* Dialog function for the About box. * Since this is a simple box with only one button, WM_COMMAND is assumed * to be a click on that button (the command number is not checked). */ BOOL FAR PASCAL AboutBox( hDlg, wMsg, wParam, lParam ) HWND hDlg; /* Window handle */ unsigned wMsg; /* Message number */ WORD wParam; /* Word parameter for the message */ LONG lParam; /* Long parameter for the message */ { switch( wMsg ) { case WM_COMMAND: EndDialog( hDlg, TRUE ); return TRUE; } return FALSE; }