在Windows环境下,不论是使用Visual C++还是Delphi或是其他一些软件开发工具开发的应用程序,尽管存在着差别,但有一点是相同的:都是运行于Windows操作系统之下的。在程序开发过程中也经常要在自己的应用程序中加入一些Windows系统本身就有的功能,比如文件的拷贝、删除、查找以及运行程序等等。而这些功能在Windows操作系统下都是具备的,显然如果能直接从系统中调用这些功能将不仅仅减少程序的大小和开发人员的工作量,而且由于是直接通过操作系统来完成这些功能,将会大大减小这部分程序出现异常错误的概率。Windows系统虽说也存在不少错误,但常用功能的错误还是比较少的,而且通过补丁程序可以更低限度减少系统错误,因此程序员可以将调试检错的注意力放在应用程序的其他地方,对于调用系统功能这部分代码则可以不必投入太大的精力去调试,因为这部分调试的工作在操作系统发布的时候就已经由微软做好了。本文通过外壳编程,实现了搜寻文件、运行程序、控制工具条、最大最小化窗口的功能,程序的运行界面如图一所示:
…… SHFILEOPSTRUCT FileOp; //外壳的文件操作结构 FileOp.hwnd=m_hWnd; //设置句柄 //设置操作方式,拷贝用FO_COPY,删除用 FO_DELETE FileOp.wFunc=FO_COPY; FileOp.pFrom=m_source; //源文件路径 FileOp.pTo=m_detect; //目标文件路径 FileOp.fFlags=FOF_ALLOWUNDO; //允许恢复 FileOp.hNameMappings=NULL; FileOp.lpszProgressTitle=strTitle; //设置标题 SHFileOperation(&FileOp); //执行外壳拷贝 if(FileOp.fAnyOperationsAborted) //监测有无中止 TRACE("An Operation was aborted!!!\n"); …… |
…… CoInitialize(NULL); //初始化COM …… CoUninitialize(); //终止COM代码 …… |
…… EXTERN_C const IID IID_IShellDispatch; #if defined(__cplusplus) && !defined(CINTERFACE) interface DECLSPEC_UUID("D8F015C0-C278-11CE-A49E-444553540000") IShellDispatch : public Idispatch { public: …… virtual HRESULT STDMETHODCALLTYPE MinimizeAll( void) = 0; virtual HRESULT STDMETHODCALLTYPE UndoMinimizeALL( void) = 0; virtual HRESULT STDMETHODCALLTYPE FileRun( void) = 0; virtual HRESULT STDMETHODCALLTYPE CascadeWindows( void) = 0; virtual HRESULT STDMETHODCALLTYPE TileVertically( void) = 0; virtual HRESULT STDMETHODCALLTYPE TileHorizontally( void) = 0; virtual HRESULT STDMETHODCALLTYPE ShutdownWindows( void) = 0; virtual HRESULT STDMETHODCALLTYPE Suspend( void) = 0; virtual HRESULT STDMETHODCALLTYPE SetTime( void) = 0; virtual HRESULT STDMETHODCALLTYPE TrayProperties( void) = 0; virtual HRESULT STDMETHODCALLTYPE Help( void) = 0; virtual HRESULT STDMETHODCALLTYPE FindFiles( void) = 0; virtual HRESULT STDMETHODCALLTYPE FindComputer( void) = 0; }; …… |
…… HRESULT sc;//返回结果 IShellDispatch *pShellDisp = NULL; //初始化接口指针 //直接创建COM对象 sc = CoCreateInstance( CLSID_Shell,//指定待创建的COM对象标识符 NULL, //指定被聚合时的外部对象的接口指针 CLSCTX_SERVER, //指定组件类别,可以指定进程内组件进程外组件或者进程内控制对象。 IID_IDispatch, //指定接口ID,需要注意的是这里指的是待 //创建的COM对象的接口ID,而非类厂对象的接口标识符 (LPVOID *) &pShellDisp );//存放函数返回的对象的接口指针 /* 在上述代码中,CoCreateInstance首先调用CoGetClassObject函数创建类厂对象,然后用得到的类厂对象的接口指针创建真正的COM对象,最后把类厂对象释放并返回,这样就很好的把类厂屏蔽起来,使用户用起来更为简单。*/ if( FAILED(sc) )//必须用FAILED 或SUCCECCED来判断COM对象是否创建成功 return; pShellDisp->FindFiles(); //调用COM对象里的方法 pShellDisp->Release(); //释放申请到的接口指针 …… |
///////////////////////////////////// #define INC_OLE2 #define WIN32_LEAN_AND_MEAN #define STRICT #include <windows.h> #include <windowsx.h> #include <commctrl.h> #include <shlguid.h> #include <exdisp.h> #include "taskbar.h" #include "resource.h" // data static WNDPROC g_pfnOldProc; static HWND g_hwndButton=NULL; static HWND g_hDlg=NULL; static HINSTANCE g_hInstance; static HICON g_hIconLarge; static HICON g_hIconSmall; // functions static VOID OnRunPrograms( VOID ); static VOID OnFindFiles( VOID ); static VOID OnMinimizeAll( VOID ); static VOID OnUndoMinimize( VOID ); static VOID OnTaskbarProperties( VOID ); static VOID OnAddTab( HWND ); static VOID OnDeleteTab( VOID ); static VOID OnInitDialog( HWND ); static VOID OnButtonActivation( VOID ); // callbacks LRESULT CALLBACK APP_DlgProc( HWND, UINT, WPARAM, LPARAM ); LRESULT CALLBACK ButtonProc( HWND, UINT, WPARAM, LPARAM ); INT APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevious, LPSTR lpsz, INT iCmd ) { BOOL b; g_hIconLarge = (HICON) LoadImage( hInstance, "APP_ICON", IMAGE_ICON, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CXICON), 0 ); g_hIconSmall = (HICON) LoadImage( hInstance, "APP_ICON", IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CXSMICON), 0 ); // initialize OLE libraries CoInitialize(NULL); InitCommonControls(); // run main dialog g_hInstance = hInstance; b = DialogBox( hInstance, "DLG_MAIN", NULL, (DLGPROC)APP_DlgProc ); // exit DestroyIcon( g_hIconLarge ); DestroyIcon( g_hIconSmall ); // free the objects used by ITaskbarList DestroyWindow( g_hwndButton ); OnDeleteTab(); CoUninitialize(); return b; } LRESULT CALLBACK APP_DlgProc( HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam ) { switch( uiMsg ) { case WM_INITDIALOG: OnInitDialog( hDlg ); break; case WM_COMMAND: switch( wParam ) { case IDC_FINDFILES: OnFindFiles(); return 1; case IDC_RUNPROGRAMS: OnRunPrograms(); return 1; case IDC_MINIMIZE: OnMinimizeAll(); return 1; case IDC_UNDOMINIMIZE: OnUndoMinimize(); return 1; case IDC_PROPERTIES: OnTaskbarProperties(); return 1; case IDC_ADDTAB: OnAddTab( hDlg ); return 1; case IDC_DELETETAB: OnDeleteTab(); return 1; case IDCANCEL: EndDialog( hDlg, FALSE ); return 0; } break; } return 0; } VOID OnFindFiles( VOID ) { HRESULT sc; IShellDispatch *pShellDisp = NULL; sc = CoCreateInstance( CLSID_Shell, NULL, CLSCTX_SERVER, IID_IDispatch, (LPVOID *) &pShellDisp ); if( FAILED(sc) ) return; pShellDisp->FindFiles(); pShellDisp->Release(); return; } VOID OnTaskbarProperties( VOID ) { HRESULT sc; IShellDispatch *pShellDisp = NULL; sc = CoCreateInstance( CLSID_Shell, NULL, CLSCTX_SERVER,IID_IDispatch, (LPVOID *) &pShellDisp ); if( FAILED(sc) ) return; pShellDisp->TrayProperties(); pShellDisp->Release(); return; } VOID OnRunPrograms( VOID ) { HRESULT sc; IShellDispatch *pShellDisp = NULL; sc = CoCreateInstance( CLSID_Shell, NULL, CLSCTX_SERVER, IID_IShellDispatch, (LPVOID *) &pShellDisp ); if( FAILED(sc) ) return; pShellDisp->FileRun(); pShellDisp->Release(); return; } VOID OnMinimizeAll( VOID ) { HRESULT sc; IShellDispatch *pShellDisp = NULL; sc = CoCreateInstance( CLSID_Shell, NULL, CLSCTX_SERVER, IID_IDispatch, (LPVOID *) &pShellDisp ); if( FAILED(sc) ) return; pShellDisp->MinimizeAll(); pShellDisp->Release(); return; } VOID OnUndoMinimize( VOID ) { HRESULT sc; IShellDispatch *pShellDisp = NULL; sc = CoCreateInstance( CLSID_Shell, NULL, CLSCTX_SERVER, IID_IDispatch, (LPVOID *) &pShellDisp ); if( FAILED(sc) ) return; pShellDisp->UndoMinimizeALL(); pShellDisp->Release(); return; } VOID OnInitDialog( HWND hDlg ) { // set the icons (T/F as to Large/Small icon) g_hDlg = hDlg; SendMessage( hDlg, WM_SETICON, FALSE, (LPARAM)g_hIconSmall ); SendMessage( hDlg, WM_SETICON, TRUE, (LPARAM)g_hIconLarge ); } VOID OnAddTab( HWND hWnd ) { static BOOL g_bFirstTime=TRUE; HRESULT sc; ITaskbarList *pDisp = NULL; sc = CoCreateInstance( CLSID_TaskbarList, NULL, CLSCTX_SERVER, IID_ITaskbarList, (LPVOID *) &pDisp ); if( FAILED(sc) ) return; // call the first time only if( g_bFirstTime ) { g_bFirstTime = FALSE; pDisp->HrInit(); // create a new button window g_hwndButton = CreateWindow( "button", "My Button", WS_CLIPSIBLINGS|BS_PUSHBUTTON,0, 0, 58, 14, hWnd, NULL, g_hInstance, NULL ); g_pfnOldProc = (WNDPROC) SubclassWindow( g_hwndButton, ButtonProc ); } pDisp->AddTab( g_hwndButton ); pDisp->Release(); return; } VOID OnDeleteTab( VOID ) { HRESULT sc; ITaskbarList *pDisp = NULL; sc = CoCreateInstance( CLSID_TaskbarList, NULL, CLSCTX_SERVER, IID_ITaskbarList, (LPVOID *) &pDisp ); if( FAILED(sc) ) return; pDisp->DeleteTab( g_hwndButton ); pDisp->Release(); return; } LRESULT CALLBACK ButtonProc( HWND hwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam ) { switch( uiMsg ) { case WM_NCACTIVATE: if( wParam==TRUE ) OnButtonActivation(); break; } return CallWindowProc( g_pfnOldProc, hwnd, uiMsg, wParam, lParam ); } VOID OnButtonActivation( VOID ) { HMENU hmenu; RECT r; LONG x, y; // get some window handles HWND h0=FindWindow("Shell_TrayWnd", NULL ); HWND h1=FindWindowEx(h0,NULL,"RebarWindow32", NULL); HWND h2=FindWindowEx(h1,NULL,"MSTaskSwWClass", NULL); HWND h3=FindWindowEx(h2,NULL,"SysTabControl32", NULL); GetWindowRect( h3, &r ); // get the currently selected button and // create a new popup menu hmenu = CreatePopupMenu(); INT i=TabCtrl_GetCurSel( h3 ); if( i==-1 ) { AppendMenu( hmenu, MF_STRING, IDC_DELETETAB,"&Close" ); } else { AppendMenu( hmenu, MF_STRING, IDC_MINIMIZE,"&Minimize All" ); AppendMenu( hmenu, MF_STRING, IDC_UNDOMINIMIZE,"&Undo Minimize All" ); AppendMenu( hmenu, MF_SEPARATOR, 0, NULL ); AppendMenu( hmenu, MF_STRING, IDC_PROPERTIES,"&Taskbar Properties" ); } // set and immediately reset its size to get // the current width and height LONG l = TabCtrl_SetItemSize( h3, 0, 0 ); TabCtrl_SetItemSize( h3, LOWORD(l), HIWORD(l) ); // have the menu to appear just above the button if( i==-1 ) { POINT pt; GetCursorPos( &pt ); x = pt.x; y = pt.y; } else { x = r.left + LOWORD(l)*i+3; y = GetSystemMetrics(SM_CYSCREEN)-(HIWORD(l)+1); } TrackPopupMenu( hmenu, TPM_BOTTOMALIGN, x, y, 0, g_hDlg, 0); DestroyMenu( hmenu ); return; } |