下载地址: http://www.cppblog.com/Files/justin-shi/MuiltiProcessTab.rar 关键代码说明: // 判断创建主窗口还是标签页 int argc = 0; LPCWSTR cmd = GetCommandLine(); LPWSTR* argv = CommandLineToArgvW(cmd, &argc); // 创建 Tab Header if (argc < 2) { CreateTabCtrl(); } // 创建 Tab Page else { CreateTabPage(argv); } // 作为TabCtrl打开 void CMuiltiProcessTabApp::CreateTabCtrl() { CMuiltiProcessTabDlg dlg; m_pMainWnd = &dlg; INT_PTR nResponse = dlg.DoModal(); } // 作为Tab页打开 void CMuiltiProcessTabApp::CreateTabPage(LPWSTR* argv) { // // 得到TabCtrl的句柄信息 // MuiltiProcessTabHandles handles; HANDLE hFile = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MEMFILE_SIZE, szMemfileName); if (hFile == NULL) { AfxMessageBox(_T("CreateFileMapping 失败")); return; } char *pMemChild = (char*)MapViewOfFile(hFile, FILE_MAP_ALL_ACCESS, 0, 0, MEMFILE_SIZE); CopyMemory(&handles, pMemChild, sizeof(handles)); UnmapViewOfFile(pMemChild); CloseHandle(hFile); // // 创建web控件 // CRect rcMainTab; ::GetClientRect(handles.hWndTab, &rcMainTab); CWnd wnd; wnd.Attach(handles.hWndTab); wndBrowser.CreateControl( CLSID_WebBrowser, argv[1], WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, CRect(0, 23, rcMainTab.right-3, rcMainTab.bottom), &wnd, IDC_WEBBROWSER); wnd.Detach(); LPUNKNOWN IUnKnown = wndBrowser.GetControlUnknown(); CComPtr<IWebBrowser2> browser; IUnKnown->QueryInterface(&browser); CComVariant url(argv[1]); CComVariant cookie(_T("")); browser->Navigate2(&url, NULL, NULL, NULL, &cookie); // 将自己添加到Tab页中 SetParent(wndBrowser.m_hWnd, handles.hWndTab); SetWindowText(wndBrowser.m_hWnd, argv[1]); SendMessage(handles.hWndMain, WM_ADDPAGE, (WPARAM)wndBrowser.m_hWnd, 0); // // 开始消息循环 // MSG msg; while (GetMessage(&msg, 0, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } } // // 退出 // void CMuiltiProcessTabDlg::OnDestroy() { CDialog::OnDestroy(); while (!listPages.empty()) { PostThreadMessage( GetWindowThreadProcessId(listPages.back(), NULL), WM_QUIT, 0, 0); Sleep(0); listPages.pop_back(); } if (hMemFile) { CloseHandle(hMemFile); } } // // 调整窗口大小, 位置 // void CMuiltiProcessTabDlg::OnSize(UINT nType, int cx, int cy) { CDialog::OnSize(nType, cx, cy); if (editAddr.GetSafeHwnd()) { editAddr.MoveWindow(0, 0, cx-85, 25); btnAdd.MoveWindow(cx-80, 0, 80, 25); tabMain.MoveWindow(0, 26, cx, cy-26); for (size_t i=0; i<listPages.size(); i++) { ::MoveWindow(listPages[i], 0, 23, cx-3, cy-26-23, FALSE); } } } // 作为TabCtrl打开 void CMuiltiProcessTabDlg::CreateTabCtrl() { CRect rc; GetClientRect(&rc); // 创建主窗口的控件 editAddr.Create(WS_VISIBLE | WS_CHILD | WS_BORDER | WS_TABSTOP | WS_CLIPSIBLINGS, CRect(0, 0, rc.right-85, 25), this, IDC_EDIT_ADDRESS); editAddr.SetFont(GetFont()); btnAdd.Create(_T("打开"), BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_CLIPSIBLINGS, CRect(rc.right-80, 0, rc.right, 25), this, IDC_BUTTON_ADD); btnAdd.SetFont(GetFont()); tabMain.Create(WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, CRect(0, 26, rc.right, rc.bottom), this, IDC_TAB_MAIN); tabMain.SetFont(GetFont()); editAddr.SetWindowText(_T("http://www.google.com")); handles.hWndMain = m_hWnd; handles.hWndTab = tabMain.m_hWnd; // 设置默认按钮 SetDefID(IDC_BUTTON_ADD); // 创建一个内存镜像文件 hMemFile = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MEMFILE_SIZE, szMemfileName); if (hMemFile == NULL) { AfxMessageBox(_T("CreateFileMapping 失败")); return; } char *pMemMain = (char*)MapViewOfFile(hMemFile, FILE_MAP_ALL_ACCESS, 0, 0, MEMFILE_SIZE); CopyMemory(pMemMain, &handles, sizeof(handles)); UnmapViewOfFile(pMemMain); } // 添加页面 LRESULT CMuiltiProcessTabDlg::OnAddPage(WPARAM wParam, LPARAM lParam) { HWND hWnd = (HWND)wParam; TCHAR title[4096]; ::GetWindowText(hWnd, title, 4096); int nItem = tabMain.GetCurSel(); nItem = nItem + 1; tabMain.InsertItem(nItem, title); listPages.insert(listPages.begin()+nItem, hWnd); tabMain.SetCurSel(nItem); return 0; } // 打开页面 void CMuiltiProcessTabDlg::OnBnClickedButtonAdd() { STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); ZeroMemory(&pi, sizeof(pi)); CString url; editAddr.GetWindowText(url); TCHAR* szCmdline = _tcsdup( _T("/"MuiltiProcessTab.exe/" ") + url); if (!CreateProcess(NULL, szCmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { AfxMessageBox (_T("创建失败!")); } } // 切换标签页 void CMuiltiProcessTabDlg::OnTabMainSelChanged(NMHDR* nmhdr, LRESULT* result) { int nItem = tabMain.GetCurSel(); for (size_t i=0; i<listPages.size(); i++) { if (i == nItem) { ::ShowWindow(listPages[i], SW_SHOW); } else { ::ShowWindow(listPages[i], SW_HIDE); } } } // 关闭标签页 LRESULT CMuiltiProcessTabDlg::OnTabPageClosed(WPARAM wParam, LPARAM lParam) { int nItem = tabMain.GetCurSel(); tabMain.DeleteItem(nItem); if (nItem > 0) { tabMain.SetCurSel(nItem-1); } else { tabMain.SetCurSel(0); } OnTabMainSelChanged(0, 0); PostThreadMessage( GetWindowThreadProcessId(listPages[nItem], NULL), WM_QUIT, 0, 0); Sleep(0); listPages.erase(listPages.begin()+nItem); return 0; }