Преглед на файлове

辅助管理,未完成。

sat23 преди 3 години
родител
ревизия
18cc7474b9

+ 20 - 0
AssistManager/AssistManager.sln

@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AssistManager", "AssistManager\AssistManager.vcproj", "{0AEAF68A-1872-40AD-BB8D-4354E964C2CD}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Release|Win32 = Release|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{0AEAF68A-1872-40AD-BB8D-4354E964C2CD}.Debug|Win32.ActiveCfg = Debug|Win32
+		{0AEAF68A-1872-40AD-BB8D-4354E964C2CD}.Debug|Win32.Build.0 = Debug|Win32
+		{0AEAF68A-1872-40AD-BB8D-4354E964C2CD}.Release|Win32.ActiveCfg = Release|Win32
+		{0AEAF68A-1872-40AD-BB8D-4354E964C2CD}.Release|Win32.Build.0 = Release|Win32
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 79 - 0
AssistManager/AssistManager/AssistManager.cpp

@@ -0,0 +1,79 @@
+
+// AssistManager.cpp : 定义应用程序的类行为。
+//
+
+#include "stdafx.h"
+#include "AssistManager.h"
+#include "AssistManagerDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+
+// CAssistManagerApp
+
+BEGIN_MESSAGE_MAP(CAssistManagerApp, CWinAppEx)
+	ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
+END_MESSAGE_MAP()
+
+
+// CAssistManagerApp 构造
+
+CAssistManagerApp::CAssistManagerApp()
+{
+	// TODO: 在此处添加构造代码,
+	// 将所有重要的初始化放置在 InitInstance 中
+}
+
+
+// 唯一的一个 CAssistManagerApp 对象
+
+CAssistManagerApp theApp;
+
+
+// CAssistManagerApp 初始化
+
+BOOL CAssistManagerApp::InitInstance()
+{
+	// 如果一个运行在 Windows XP 上的应用程序清单指定要
+	// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
+	//则需要 InitCommonControlsEx()。否则,将无法创建窗口。
+	INITCOMMONCONTROLSEX InitCtrls;
+	InitCtrls.dwSize = sizeof(InitCtrls);
+	// 将它设置为包括所有要在应用程序中使用的
+	// 公共控件类。
+	InitCtrls.dwICC = ICC_WIN95_CLASSES;
+	InitCommonControlsEx(&InitCtrls);
+
+	CWinAppEx::InitInstance();
+
+	AfxEnableControlContainer();
+
+	// 标准初始化
+	// 如果未使用这些功能并希望减小
+	// 最终可执行文件的大小,则应移除下列
+	// 不需要的特定初始化例程
+	// 更改用于存储设置的注册表项
+	// TODO: 应适当修改该字符串,
+	// 例如修改为公司或组织名
+	SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
+
+	CAssistManagerDlg dlg;
+	m_pMainWnd = &dlg;
+	INT_PTR nResponse = dlg.DoModal();
+	if (nResponse == IDOK)
+	{
+		// TODO: 在此放置处理何时用
+		//  “确定”来关闭对话框的代码
+	}
+	else if (nResponse == IDCANCEL)
+	{
+		// TODO: 在此放置处理何时用
+		//  “取消”来关闭对话框的代码
+	}
+
+	// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
+	//  而不是启动应用程序的消息泵。
+	return FALSE;
+}

+ 32 - 0
AssistManager/AssistManager/AssistManager.h

@@ -0,0 +1,32 @@
+
+// AssistManager.h : PROJECT_NAME 应用程序的主头文件
+//
+
+#pragma once
+
+#ifndef __AFXWIN_H__
+	#error "在包含此文件之前包含“stdafx.h”以生成 PCH 文件"
+#endif
+
+#include "resource.h"		// 主符号
+
+
+// CAssistManagerApp:
+// 有关此类的实现,请参阅 AssistManager.cpp
+//
+
+class CAssistManagerApp : public CWinAppEx
+{
+public:
+	CAssistManagerApp();
+
+// 重写
+	public:
+	virtual BOOL InitInstance();
+
+// 实现
+
+	DECLARE_MESSAGE_MAP()
+};
+
+extern CAssistManagerApp theApp;

+ 197 - 0
AssistManager/AssistManager/AssistManager.rc

@@ -0,0 +1,197 @@
+// Microsoft Visual C++ 生成的资源脚本。
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// 从 TEXTINCLUDE 2 资源生成。
+//
+#ifndef APSTUDIO_INVOKED
+#include "targetver.h"
+#endif
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+	"#ifndef APSTUDIO_INVOKED\r\n"
+    "#include ""targetver.h""\r\n"
+    "#endif\r\n"
+    "#include ""afxres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+    "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
+    "#define _AFX_NO_OLE_RESOURCES\r\n"
+    "#define _AFX_NO_TRACKER_RESOURCES\r\n"
+    "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
+    "\r\n"
+    "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)\r\n"
+    "LANGUAGE 4, 2\r\n"
+    "#pragma code_page(936)\r\n"
+    "#include ""res\\AssistManager.rc2""  // 非 Microsoft Visual C++ 编辑的资源\r\n"
+    "#include ""l.CHS\\afxres.rc""  	// 标准组件\r\n"
+    "#endif\r\n"
+    "\0"
+END
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// 图标
+//
+
+// ID 值最低的图标放在最前面,以确保应用程序图标
+// 在所有系统中保持一致。
+IDR_MAINFRAME           ICON         "res\\AssistManager.ico"
+
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
+LANGUAGE 4, 2
+#pragma code_page(936)
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// 对话框
+//
+
+IDD_ABOUTBOX DIALOGEX 0, 0, 170, 62
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "关于 AssistManager"
+FONT 9, "MS Shell Dlg"
+BEGIN
+    ICON            IDR_MAINFRAME,IDC_STATIC,14,14,21,20
+    LTEXT           "AssistManager,1.0 版",IDC_STATIC,42,14,114,8,SS_NOPREFIX
+    LTEXT           "Copyright (C) 2022",IDC_STATIC,42,26,114,8
+    DEFPUSHBUTTON   "确定",IDOK,113,41,50,14,WS_GROUP
+END
+
+IDD_ASSISTMANAGER_DIALOG DIALOGEX  0, 0, 320, 200
+STYLE DS_SHELLFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION
+ | DS_MODALFRAME
+ | WS_SYSMENU
+EXSTYLE WS_EX_APPWINDOW
+CAPTION "AssistManager"
+FONT 9, "MS Shell Dlg"
+BEGIN
+    DEFPUSHBUTTON   "确定",IDOK,209,179,50,14
+    PUSHBUTTON      "取消",IDCANCEL,263,179,50,14
+	CTEXT           "TODO: 在此放置对话框控件。",IDC_STATIC,10,96,300,8
+END
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// 版本
+//
+
+VS_VERSION_INFO     VERSIONINFO
+  FILEVERSION       1,0,0,1
+  PRODUCTVERSION    1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+	BLOCK "StringFileInfo"
+	BEGIN
+        BLOCK "080403a8"
+		BEGIN
+            VALUE "CompanyName", "TODO: <公司名>"
+            VALUE "FileDescription", "TODO: <文件说明>"
+			VALUE "FileVersion",     "1.0.0.1"
+			VALUE "InternalName",    "AssistManager.exe"
+            VALUE "LegalCopyright", "TODO: (C) <公司名>。保留所有权利。"
+			VALUE "OriginalFilename","AssistManager.exe"
+            VALUE "ProductName", "TODO: <产品名>"
+			VALUE "ProductVersion",  "1.0.0.1"
+		END
+	END
+	BLOCK "VarFileInfo"
+	BEGIN
+		VALUE "Translation", 0x0804, 936
+    END
+END
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+    IDD_ABOUTBOX, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 163
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 55
+    END
+    IDD_ASSISTMANAGER_DIALOG, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 313
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 193
+    END
+END
+#endif    // APSTUDIO_INVOKED
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// 字符串表
+//
+
+STRINGTABLE
+BEGIN
+    IDS_ABOUTBOX            "关于 AssistManager(&A)..."
+END
+
+
+#endif
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// 从 TEXTINCLUDE 3 资源生成。
+//
+#define _AFX_NO_SPLITTER_RESOURCES
+#define _AFX_NO_OLE_RESOURCES
+#define _AFX_NO_TRACKER_RESOURCES
+#define _AFX_NO_PROPERTY_RESOURCES
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
+LANGUAGE 4, 2
+#pragma code_page(936)
+#include "res\\AssistManager.rc2"  // 非 Microsoft Visual C++ 编辑的资源
+#include "l.CHS\\afxres.rc"  	// 标准组件
+#endif
+/////////////////////////////////////////////////////////////////////////////
+#endif    // 不是 APSTUDIO_INVOKED
+

+ 276 - 0
AssistManager/AssistManager/AssistManager.vcproj

@@ -0,0 +1,276 @@
+<?xml version="1.0" encoding="gb2312"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="AssistManager"
+	ProjectGUID="{0AEAF68A-1872-40AD-BB8D-4354E964C2CD}"
+	RootNamespace="AssistManager"
+	Keyword="MFCProj"
+	TargetFrameworkVersion="196613"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			UseOfMFC="2"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="_DEBUG"
+				MkTypLibCompatible="false"
+				ValidateParameters="true"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUG"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="_DEBUG"
+				Culture="2052"
+				AdditionalIncludeDirectories="$(IntDir)"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			UseOfMFC="2"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+				PreprocessorDefinitions="NDEBUG"
+				MkTypLibCompatible="false"
+				ValidateParameters="true"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG"
+				MinimalRebuild="false"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+				PreprocessorDefinitions="NDEBUG"
+				Culture="2052"
+				AdditionalIncludeDirectories="$(IntDir)"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="2"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Ô´Îļþ"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\AssistManager.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\AssistManagerDlg.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\PipeService.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\stdafx.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+			</File>
+		</Filter>
+		<Filter
+			Name="Í·Îļþ"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\AssistManager.h"
+				>
+			</File>
+			<File
+				RelativePath=".\AssistManagerDlg.h"
+				>
+			</File>
+			<File
+				RelativePath=".\PipeService.h"
+				>
+			</File>
+			<File
+				RelativePath=".\Resource.h"
+				>
+			</File>
+			<File
+				RelativePath=".\stdafx.h"
+				>
+			</File>
+			<File
+				RelativePath=".\targetver.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="×ÊÔ´Îļþ"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+			<File
+				RelativePath=".\res\AssistManager.ico"
+				>
+			</File>
+			<File
+				RelativePath=".\AssistManager.rc"
+				>
+			</File>
+			<File
+				RelativePath=".\res\AssistManager.rc2"
+				>
+			</File>
+		</Filter>
+		<File
+			RelativePath=".\ReadMe.txt"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

+ 153 - 0
AssistManager/AssistManager/AssistManagerDlg.cpp

@@ -0,0 +1,153 @@
+
+// AssistManagerDlg.cpp : 实现文件
+//
+
+#include "stdafx.h"
+#include "AssistManager.h"
+#include "AssistManagerDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+
+// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
+
+class CAboutDlg : public CDialog
+{
+public:
+	CAboutDlg();
+
+// 对话框数据
+	enum { IDD = IDD_ABOUTBOX };
+
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
+
+// 实现
+protected:
+	DECLARE_MESSAGE_MAP()
+};
+
+CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
+{
+}
+
+void CAboutDlg::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+}
+
+BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
+END_MESSAGE_MAP()
+
+
+// CAssistManagerDlg 对话框
+
+
+
+
+CAssistManagerDlg::CAssistManagerDlg(CWnd* pParent /*=NULL*/)
+	: CDialog(CAssistManagerDlg::IDD, pParent)
+{
+	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
+}
+
+void CAssistManagerDlg::DoDataExchange(CDataExchange* pDX)
+{
+	CDialog::DoDataExchange(pDX);
+}
+
+BEGIN_MESSAGE_MAP(CAssistManagerDlg, CDialog)
+	ON_WM_SYSCOMMAND()
+	ON_WM_PAINT()
+	ON_WM_QUERYDRAGICON()
+	//}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+
+// CAssistManagerDlg 消息处理程序
+
+BOOL CAssistManagerDlg::OnInitDialog()
+{
+	CDialog::OnInitDialog();
+
+	// 将“关于...”菜单项添加到系统菜单中。
+
+	// IDM_ABOUTBOX 必须在系统命令范围内。
+	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
+	ASSERT(IDM_ABOUTBOX < 0xF000);
+
+	CMenu* pSysMenu = GetSystemMenu(FALSE);
+	if (pSysMenu != NULL)
+	{
+		BOOL bNameValid;
+		CString strAboutMenu;
+		bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
+		ASSERT(bNameValid);
+		if (!strAboutMenu.IsEmpty())
+		{
+			pSysMenu->AppendMenu(MF_SEPARATOR);
+			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
+		}
+	}
+
+	// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
+	//  执行此操作
+	SetIcon(m_hIcon, TRUE);			// 设置大图标
+	SetIcon(m_hIcon, FALSE);		// 设置小图标
+
+	// TODO: 在此添加额外的初始化代码
+
+	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
+}
+
+void CAssistManagerDlg::OnSysCommand(UINT nID, LPARAM lParam)
+{
+	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
+	{
+		CAboutDlg dlgAbout;
+		dlgAbout.DoModal();
+	}
+	else
+	{
+		CDialog::OnSysCommand(nID, lParam);
+	}
+}
+
+// 如果向对话框添加最小化按钮,则需要下面的代码
+//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
+//  这将由框架自动完成。
+
+void CAssistManagerDlg::OnPaint()
+{
+	if (IsIconic())
+	{
+		CPaintDC dc(this); // 用于绘制的设备上下文
+
+		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
+
+		// 使图标在工作区矩形中居中
+		int cxIcon = GetSystemMetrics(SM_CXICON);
+		int cyIcon = GetSystemMetrics(SM_CYICON);
+		CRect rect;
+		GetClientRect(&rect);
+		int x = (rect.Width() - cxIcon + 1) / 2;
+		int y = (rect.Height() - cyIcon + 1) / 2;
+
+		// 绘制图标
+		dc.DrawIcon(x, y, m_hIcon);
+	}
+	else
+	{
+		CDialog::OnPaint();
+	}
+}
+
+//当用户拖动最小化窗口时系统调用此函数取得光标
+//显示。
+HCURSOR CAssistManagerDlg::OnQueryDragIcon()
+{
+	return static_cast<HCURSOR>(m_hIcon);
+}
+

+ 32 - 0
AssistManager/AssistManager/AssistManagerDlg.h

@@ -0,0 +1,32 @@
+
+// AssistManagerDlg.h : 头文件
+//
+
+#pragma once
+
+
+// CAssistManagerDlg 对话框
+class CAssistManagerDlg : public CDialog
+{
+// 构造
+public:
+	CAssistManagerDlg(CWnd* pParent = NULL);	// 标准构造函数
+
+// 对话框数据
+	enum { IDD = IDD_ASSISTMANAGER_DIALOG };
+
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持
+
+
+// 实现
+protected:
+	HICON m_hIcon;
+
+	// 生成的消息映射函数
+	virtual BOOL OnInitDialog();
+	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
+	afx_msg void OnPaint();
+	afx_msg HCURSOR OnQueryDragIcon();
+	DECLARE_MESSAGE_MAP()
+};

+ 721 - 0
AssistManager/AssistManager/PipeService.cpp

@@ -0,0 +1,721 @@
+#include "StdAfx.h"
+#include "IOCPModel.h"
+#include "MainDlg.h"
+
+// 每一个处理器上产生多少个线程(为了最大限度的提升服务器性能,详见配套文档)
+#define WORKER_THREADS_PER_PROCESSOR 2
+// 同时投递的Accept请求的数量(这个要根据实际的情况灵活设置)
+#define MAX_POST_ACCEPT              10
+// 传递给Worker线程的退出信号
+#define EXIT_CODE                    NULL
+
+
+// 释放指针和句柄资源的宏
+
+// 释放指针宏
+#define RELEASE(x)                      {if(x != NULL ){delete x;x=NULL;}}
+// 释放句柄宏
+#define RELEASE_HANDLE(x)               {if(x != NULL && x!=INVALID_HANDLE_VALUE){ CloseHandle(x);x = NULL;}}
+// 释放Socket宏
+#define RELEASE_SOCKET(x)               {if(x !=INVALID_SOCKET) { closesocket(x);x=INVALID_SOCKET;}}
+
+
+
+CIOCPModel::CIOCPModel(void)
+{
+    m_nThreads = 0;
+    m_hShutdownEvent = NULL;
+    m_hIOCompletionPort = NULL;
+    m_phWorkerThreads= NULL;
+    m_pMain = NULL;
+}
+
+CIOCPModel::~CIOCPModel(void)
+{
+	// 确保资源彻底释放
+	this->Stop();
+}
+
+
+///////////////////////////////////////////////////////////////////
+// 工作者线程:  为IOCP请求服务的工作者线程
+//         也就是每当完成端口上出现了完成数据包,就将之取出来进行处理的线程
+///////////////////////////////////////////////////////////////////
+
+DWORD WINAPI CIOCPModel::_WorkerThread(LPVOID lpParam)
+{    
+	THREADPARAMS_WORKER* pParam = (THREADPARAMS_WORKER*)lpParam;
+	CIOCPModel* pIOCPModel = (CIOCPModel*)pParam->pIOCPModel;
+	int nThreadNo = (int)pParam->nThreadNo;
+
+	pIOCPModel->_ShowMessage("工作者线程启动,ID: %d.",nThreadNo);
+
+	OVERLAPPED           *pOverlapped = NULL;
+	PER_SOCKET_CONTEXT   *pSocketContext = NULL;
+	DWORD                dwBytesTransfered = 0;
+
+	// 循环处理请求,知道接收到Shutdown信息为止
+	while (WAIT_OBJECT_0 != WaitForSingleObject(pIOCPModel->m_hShutdownEvent, 0))
+	{
+		BOOL bReturn = GetQueuedCompletionStatus(
+			pIOCPModel->m_hIOCompletionPort,
+			&dwBytesTransfered,
+			(PULONG_PTR)&pSocketContext,
+			&pOverlapped,
+			INFINITE);
+
+		// 如果收到的是退出标志,则直接退出
+		if ( EXIT_CODE==(DWORD)pSocketContext )
+		{
+			break;
+		}
+
+		// 判断是否出现了错误
+		if( !bReturn )  
+		{  
+			DWORD dwErr = GetLastError();
+
+			// 显示一下提示信息
+			if( !pIOCPModel->HandleError( pSocketContext,dwErr ) )
+			{
+				break;
+			}
+
+			continue;  
+		}  
+		else  
+		{  	
+			// 读取传入的参数
+			PER_IO_CONTEXT* pIoContext = CONTAINING_RECORD(pOverlapped, PER_IO_CONTEXT, m_Overlapped);  
+
+			// 判断是否有客户端断开了
+			if((0 == dwBytesTransfered) && ( OP_RECV==pIoContext->m_OpType || OP_SEND==pIoContext->m_OpType))  
+			{  
+				pIOCPModel->_ShowMessage( _T("客户端 %s:%d 断开连接."),inet_ntoa(pSocketContext->m_ClientAddr.sin_addr), ntohs(pSocketContext->m_ClientAddr.sin_port) );
+
+				// 释放掉对应的资源
+				pIOCPModel->_RemoveContext( pSocketContext );
+
+ 				continue;  
+			}  
+			else
+			{
+				switch( pIoContext->m_OpType )  
+				{  
+					 // Accept  
+				case OP_ACCEPT:
+					{ 
+						// 为了增加代码可读性,这里用专门的_DoAccept函数进行处理连入请求
+						pIOCPModel->_DoAccpet( pSocketContext, pIoContext );						
+					}
+					break;
+
+					// RECV
+				case OP_RECV:
+					{
+						// 为了增加代码可读性,这里用专门的_DoRecv函数进行处理接收请求
+						pIOCPModel->_DoRecv( pSocketContext,pIoContext );
+					}
+					break;
+
+					// SEND
+					// 这里略过不写了,要不代码太多了,不容易理解,Send操作相对来讲简单一些
+				case OP_SEND:
+					{
+
+					}
+					break;
+				default:
+					// 不应该执行到这里
+					TRACE(_T("_WorkThread中的 pIoContext->m_OpType 参数异常.\n"));
+					break;
+				} //switch
+			}//if
+		}//if
+
+	}//while
+
+	TRACE(_T("工作者线程 %d 号退出.\n"),nThreadNo);
+
+	// 释放线程参数
+	RELEASE(lpParam);	
+
+	return 0;
+}
+
+
+
+//====================================================================================
+//
+//				    系统初始化和终止
+//
+//====================================================================================
+
+
+
+
+//////////////////////////////////////////////////////////////////
+//	启动服务器
+bool CIOCPModel::Start()
+{
+	// 初始化线程互斥量
+	InitializeCriticalSection(&m_csContextList);
+
+	// 建立系统退出的事件通知
+	m_hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+	// 初始化IOCP
+	if (false == _InitializeIOCP())
+	{
+		this->_ShowMessage(_T("初始化IOCP失败!\n"));
+		return false;
+	}
+	else
+	{
+		this->_ShowMessage("\nIOCP初始化完毕\n.");
+	}
+
+	// 初始化Socket
+	if( false==_InitializeListenSocket() )
+	{
+		this->_ShowMessage(_T("Listen Socket初始化失败!\n"));
+		this->_DeInitialize();
+		return false;
+	}
+	else
+	{
+		this->_ShowMessage("Listen Socket初始化完毕.");
+	}
+
+	this->_ShowMessage(_T("系统准备就绪,等候连接....\n"));
+
+	return true;
+}
+
+
+////////////////////////////////////////////////////////////////////
+//	开始发送系统退出消息,退出完成端口和线程资源
+void CIOCPModel::Stop()
+{
+    // 激活关闭消息通知
+    SetEvent(m_hShutdownEvent);
+
+    for (int i = 0; i < m_nThreads; i++)
+    {
+        // 通知所有的完成端口操作退出
+        PostQueuedCompletionStatus(m_hIOCompletionPort, 0, (DWORD)EXIT_CODE, NULL);
+    }
+
+    // 等待所有的客户端资源退出
+    WaitForMultipleObjects(m_nThreads, m_phWorkerThreads, TRUE, INFINITE);
+
+    // 清除客户端列表信息
+    this->_ClearContextList();
+
+    // 释放其他资源
+    this->_DeInitialize();
+
+    this->_ShowMessage("停止监听\n");
+}
+
+
+////////////////////////////////
+// 初始化完成端口
+bool CIOCPModel::_InitializeIOCP()
+{
+	// 建立第一个完成端口
+	m_hIOCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0 );
+
+	if ( NULL == m_hIOCompletionPort)
+	{
+		this->_ShowMessage(_T("建立完成端口失败!错误代码: %d!\n"), WSAGetLastError());
+		return false;
+	}
+
+	// 根据本机中的处理器数量,建立对应的线程数
+	m_nThreads = WORKER_THREADS_PER_PROCESSOR * _GetNoOfProcessors();
+	
+	// 为工作者线程初始化句柄
+	m_phWorkerThreads = new HANDLE[m_nThreads];
+	
+	// 根据计算出来的数量建立工作者线程
+	DWORD nThreadID;
+	for (int i = 0; i < m_nThreads; i++)
+	{
+		THREADPARAMS_WORKER* pThreadParams = new THREADPARAMS_WORKER;
+		pThreadParams->pIOCPModel = this;
+		pThreadParams->nThreadNo  = i+1;
+		m_phWorkerThreads[i] = ::CreateThread(0, 0, _WorkerThread, (void *)pThreadParams, 0, &nThreadID);
+	}
+
+	TRACE(" 建立 _WorkerThread %d 个.\n", m_nThreads );
+
+	return true;
+}
+
+
+/////////////////////////////////////////////////////////////////
+// 初始化Socket
+bool CIOCPModel::_InitializeListenSocket()
+{
+	// AcceptEx 和 GetAcceptExSockaddrs 的GUID,用于导出函数指针
+	GUID GuidAcceptEx = WSAID_ACCEPTEX;  
+	GUID GuidGetAcceptExSockAddrs = WSAID_GETACCEPTEXSOCKADDRS; 
+
+	// 服务器地址信息,用于绑定Socket
+	struct sockaddr_in ServerAddress;
+
+	// 生成用于监听的Socket的信息
+	m_pListenContext = new PER_SOCKET_CONTEXT;
+
+	// 需要使用重叠IO,必须得使用WSASocket来建立Socket,才可以支持重叠IO操作
+	m_pListenContext->m_Socket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
+	if (INVALID_SOCKET == m_pListenContext->m_Socket) 
+	{
+		this->_ShowMessage("初始化Socket失败,错误代码: %d.\n", WSAGetLastError());
+		return false;
+	}
+	else
+	{
+		TRACE("WSASocket() 完成.\n");
+	}
+
+	// 将Listen Socket绑定至完成端口中
+	if( NULL== CreateIoCompletionPort( (HANDLE)m_pListenContext->m_Socket, m_hIOCompletionPort,(DWORD)m_pListenContext, 0))  
+	{  
+		this->_ShowMessage("绑定 Listen Socket至完成端口失败!错误代码: %d/n", WSAGetLastError());  
+		RELEASE_SOCKET( m_pListenContext->m_Socket );
+		return false;
+	}
+	else
+	{
+		TRACE("Listen Socket绑定完成端口 完成.\n");
+	}
+
+	// 填充地址信息
+	ZeroMemory((char *)&ServerAddress, sizeof(ServerAddress));
+	ServerAddress.sin_family = AF_INET;
+	// 这里可以绑定任何可用的IP地址,或者绑定一个指定的IP地址 
+	//ServerAddress.sin_addr.s_addr = htonl(INADDR_ANY);                      
+	ServerAddress.sin_addr.s_addr = inet_addr(m_strIP.GetString());         
+	ServerAddress.sin_port = htons(m_nPort);                          
+
+	// 绑定地址和端口
+	if (SOCKET_ERROR == bind(m_pListenContext->m_Socket, (struct sockaddr *) &ServerAddress, sizeof(ServerAddress))) 
+	{
+		this->_ShowMessage("bind()函数执行错误.\n");
+		return false;
+	}
+	else
+	{
+		TRACE("bind() 完成.\n");
+	}
+
+	// 开始进行监听
+	if (SOCKET_ERROR == listen(m_pListenContext->m_Socket,SOMAXCONN))
+	{
+		this->_ShowMessage("Listen()函数执行出现错误.\n");
+		return false;
+	}
+	else
+	{
+		TRACE("Listen() 完成.\n");
+	}
+
+
+	// 为AcceptEx 准备参数,然后投递AcceptEx I/O请求
+	for( int i=0;i<MAX_POST_ACCEPT;i++ )
+	{
+		// 新建一个IO_CONTEXT
+		PER_IO_CONTEXT* pAcceptIoContext = m_pListenContext->GetNewIoContext();
+
+		if( false==this->_PostAccept( pAcceptIoContext ) )
+		{
+			m_pListenContext->RemoveContext(pAcceptIoContext);
+			return false;
+		}
+	}
+
+	this->_ShowMessage( _T("投递 %d 个AcceptEx请求完毕"),MAX_POST_ACCEPT );
+
+	return true;
+}
+
+////////////////////////////////////////////////////////////
+//	最后释放掉所有资源
+void CIOCPModel::_DeInitialize()
+{
+	// 删除客户端列表的互斥量
+	DeleteCriticalSection(&m_csContextList);
+
+	// 关闭系统退出事件句柄
+	RELEASE_HANDLE(m_hShutdownEvent);
+
+	// 释放工作者线程句柄指针
+	for( int i=0;i<m_nThreads;i++ )
+	{
+		RELEASE_HANDLE(m_phWorkerThreads[i]);
+	}
+	
+	RELEASE(m_phWorkerThreads);
+
+	// 关闭IOCP句柄
+	RELEASE_HANDLE(m_hIOCompletionPort);
+
+	// 关闭监听Socket
+	RELEASE(m_pListenContext);
+
+	this->_ShowMessage("释放资源完毕.\n");
+}
+
+
+//====================================================================================
+//
+//				    投递完成端口请求
+//
+//====================================================================================
+
+
+//////////////////////////////////////////////////////////////////
+// 投递Accept请求
+bool CIOCPModel::_PostAccept( PER_IO_CONTEXT* pAcceptIoContext )
+{
+	// 准备参数
+	DWORD dwBytes = 0;  
+	pAcceptIoContext->m_OpType = OP_ACCEPT;  
+	OVERLAPPED *p_ol = &pAcceptIoContext->m_Overlapped;
+
+    HANDLE hPipeAccept = CreateNamedPipe(
+        _T(""),            // pipe name 
+        PIPE_ACCESS_DUPLEX |     // read/write access 
+        FILE_FLAG_OVERLAPPED,    // overlapped mode 
+        PIPE_TYPE_MESSAGE |      // message-type pipe 
+        PIPE_READMODE_MESSAGE |  // message-read mode 
+        PIPE_WAIT,               // blocking mode 
+        PIPE_UNLIMITED_INSTANCES,               // number of instances 
+        0,   // output buffer size 
+        0,   // input buffer size 
+        NMPWAIT_WAIT_FOREVER,     // client time-out 
+        NULL);                   // default security attributes
+
+    HANDLE hIOCP = CreateIoCompletionPort(hPipeAccept, m_hIOCompletionPort, 10001, 0);
+    if ( hIOCP == NULL )
+    {
+        CloseHandle(hPipeAccept);
+        return false;
+    }
+
+    PER_IO_CONTEXT *pMyOverlapped = new PER_IO_CONTEXT;
+    memset(pMyOverlapped, 0, sizeof(PER_IO_CONTEXT));
+    pMyOverlapped->m_OpType = OP_ACCEPT;
+    pMyOverlapped->m_PipeAccept = hPipeAccept;
+    BOOL bRet = ConnectNamedPipe(hPipeAccept, (LPOVERLAPPED)pMyOverlapped);
+
+	if( FALSE == bRet )  
+	{  
+        CloseHandle(hPipeAccept);
+        CloseHandle(hIOCP);
+        delete pMyOverlapped;
+        pMyOverlapped = NULL;
+		_ShowMessage("创建用于Accept的Pipe失败!错误代码: %d", GetLastError()); 
+		return false;  
+	} 
+
+	return true;
+}
+
+////////////////////////////////////////////////////////////
+// 在有客户端连入的时候,进行处理
+// 流程有点复杂,你要是看不懂的话,就看配套的文档吧....
+// 如果能理解这里的话,完成端口的机制你就消化了一大半了
+
+// 总之你要知道,传入的是ListenSocket的Context,我们需要复制一份出来给新连入的Socket用
+// 原来的Context还是要在上面继续投递下一个Accept请求
+//
+bool CIOCPModel::_DoAccpet( PER_SOCKET_CONTEXT* pSocketContext, PER_IO_CONTEXT* pIoContext )
+{
+	SOCKADDR_IN* ClientAddr = NULL;
+	SOCKADDR_IN* LocalAddr = NULL;  
+	int remoteLen = sizeof(SOCKADDR_IN), localLen = sizeof(SOCKADDR_IN);  
+
+	///////////////////////////////////////////////////////////////////////////
+	// 1. 首先取得连入客户端的地址信息
+	// 这个 m_lpfnGetAcceptExSockAddrs 不得了啊~~~~~~
+	// 不但可以取得客户端和本地端的地址信息,还能顺便取出客户端发来的第一组数据,老强大了...
+	this->m_lpfnGetAcceptExSockAddrs(pIoContext->m_wsaBuf.buf, pIoContext->m_wsaBuf.len - ((sizeof(SOCKADDR_IN)+16)*2),  
+		sizeof(SOCKADDR_IN)+16, sizeof(SOCKADDR_IN)+16, (LPSOCKADDR*)&LocalAddr, &localLen, (LPSOCKADDR*)&ClientAddr, &remoteLen);  
+
+	this->_ShowMessage( _T("客户端 %s:%d 连入."), inet_ntoa(ClientAddr->sin_addr), ntohs(ClientAddr->sin_port) );
+	this->_ShowMessage( _T("客户额 %s:%d 信息:%s."),inet_ntoa(ClientAddr->sin_addr), ntohs(ClientAddr->sin_port),pIoContext->m_wsaBuf.buf );
+
+
+	//////////////////////////////////////////////////////////////////////////////////////////////////////
+	// 2. 这里需要注意,这里传入的这个是ListenSocket上的Context,这个Context我们还需要用于监听下一个连接
+	// 所以我还得要将ListenSocket上的Context复制出来一份为新连入的Socket新建一个SocketContext
+
+	PER_SOCKET_CONTEXT* pNewSocketContext = new PER_SOCKET_CONTEXT;
+	pNewSocketContext->m_Socket           = pIoContext->m_sockAccept;
+	memcpy(&(pNewSocketContext->m_ClientAddr), ClientAddr, sizeof(SOCKADDR_IN));
+
+	// 参数设置完毕,将这个Socket和完成端口绑定(这也是一个关键步骤)
+	if( false==this->_AssociateWithIOCP( pNewSocketContext ) )
+	{
+		RELEASE( pNewSocketContext );
+		return false;
+	}  
+
+
+	///////////////////////////////////////////////////////////////////////////////////////////////////
+	// 3. 继续,建立其下的IoContext,用于在这个Socket上投递第一个Recv数据请求
+	PER_IO_CONTEXT* pNewIoContext = pNewSocketContext->GetNewIoContext();
+	pNewIoContext->m_OpType       = RECV_POSTED;
+	pNewIoContext->m_sockAccept   = pNewSocketContext->m_Socket;
+	// 如果Buffer需要保留,就自己拷贝一份出来
+	//memcpy( pNewIoContext->m_szBuffer,pIoContext->m_szBuffer,MAX_BUFFER_LEN );
+
+	// 绑定完毕之后,就可以开始在这个Socket上投递完成请求了
+	if( false==this->_PostRecv( pNewIoContext) )
+	{
+		pNewSocketContext->RemoveContext( pNewIoContext );
+		return false;
+	}
+
+	/////////////////////////////////////////////////////////////////////////////////////////////////
+	// 4. 如果投递成功,那么就把这个有效的客户端信息,加入到ContextList中去(需要统一管理,方便释放资源)
+	this->_AddToContextList( pNewSocketContext );
+
+	////////////////////////////////////////////////////////////////////////////////////////////////
+	// 5. 使用完毕之后,把Listen Socket的那个IoContext重置,然后准备投递新的AcceptEx
+	pIoContext->ResetBuffer();
+	return this->_PostAccept( pIoContext ); 	
+}
+
+////////////////////////////////////////////////////////////////////
+// 投递接收数据请求
+bool CIOCPModel::_PostRecv( PER_IO_CONTEXT* pIoContext )
+{
+	// 初始化变量
+	DWORD dwFlags = 0;
+	DWORD dwBytes = 0;
+	WSABUF *p_wbuf   = &pIoContext->m_wsaBuf;
+	OVERLAPPED *p_ol = &pIoContext->m_Overlapped;
+
+	pIoContext->ResetBuffer();
+	pIoContext->m_OpType = RECV_POSTED;
+
+	// 初始化完成后,,投递WSARecv请求
+	int nBytesRecv = WSARecv( pIoContext->m_sockAccept, p_wbuf, 1, &dwBytes, &dwFlags, p_ol, NULL );
+
+	// 如果返回值错误,并且错误的代码并非是Pending的话,那就说明这个重叠请求失败了
+	if ((SOCKET_ERROR == nBytesRecv) && (WSA_IO_PENDING != WSAGetLastError()))
+	{
+		this->_ShowMessage("投递第一个WSARecv失败!");
+		return false;
+	}
+	return true;
+}
+
+/////////////////////////////////////////////////////////////////
+// 在有接收的数据到达的时候,进行处理
+bool CIOCPModel::_DoRecv( PER_SOCKET_CONTEXT* pSocketContext, PER_IO_CONTEXT* pIoContext )
+{
+	// 先把上一次的数据显示出现,然后就重置状态,发出下一个Recv请求
+	SOCKADDR_IN* ClientAddr = &pSocketContext->m_ClientAddr;
+	this->_ShowMessage( _T("收到  %s:%d 信息:%s"),inet_ntoa(ClientAddr->sin_addr), ntohs(ClientAddr->sin_port),pIoContext->m_wsaBuf.buf );
+
+	// 然后开始投递下一个WSARecv请求
+	return _PostRecv( pIoContext );
+}
+
+
+
+/////////////////////////////////////////////////////
+// 将句柄(Socket)绑定到完成端口中
+bool CIOCPModel::_AssociateWithIOCP( PER_SOCKET_CONTEXT *pContext )
+{
+	// 将用于和客户端通信的SOCKET绑定到完成端口中
+	HANDLE hTemp = CreateIoCompletionPort((HANDLE)pContext->m_Socket, m_hIOCompletionPort, (DWORD)pContext, 0);
+
+	if (NULL == hTemp)
+	{
+		this->_ShowMessage(("执行CreateIoCompletionPort()出现错误.错误代码:%d"),GetLastError());
+		return false;
+	}
+
+	return true;
+}
+
+
+
+
+//====================================================================================
+//
+//				    ContextList 相关操作
+//
+//====================================================================================
+
+
+//////////////////////////////////////////////////////////////
+// 将客户端的相关信息存储到数组中
+void CIOCPModel::_AddToContextList( PER_SOCKET_CONTEXT *pHandleData )
+{
+	EnterCriticalSection(&m_csContextList);
+
+	m_arrayClientContext.Add(pHandleData);	
+	
+	LeaveCriticalSection(&m_csContextList);
+}
+
+////////////////////////////////////////////////////////////////
+//	移除某个特定的Context
+void CIOCPModel::_RemoveContext( PER_SOCKET_CONTEXT *pSocketContext )
+{
+	EnterCriticalSection(&m_csContextList);
+
+	for( int i=0;i<m_arrayClientContext.GetCount();i++ )
+	{
+		if( pSocketContext==m_arrayClientContext.GetAt(i) )
+		{
+			RELEASE( pSocketContext );			
+			m_arrayClientContext.RemoveAt(i);			
+			break;
+		}
+	}
+
+	LeaveCriticalSection(&m_csContextList);
+}
+
+////////////////////////////////////////////////////////////////
+// 清空客户端信息
+void CIOCPModel::_ClearContextList()
+{
+	EnterCriticalSection(&m_csContextList);
+
+	for( int i=0;i<m_arrayClientContext.GetCount();i++ )
+	{
+		delete m_arrayClientContext.GetAt(i);
+	}
+
+	m_arrayClientContext.RemoveAll();
+
+	LeaveCriticalSection(&m_csContextList);
+}
+
+
+
+//====================================================================================
+//
+//				       其他辅助函数定义
+//
+//====================================================================================
+
+
+
+////////////////////////////////////////////////////////////////////
+// 获得本机的IP地址
+CString CIOCPModel::GetLocalIP()
+{
+	// 获得本机主机名
+	char hostname[MAX_PATH] = {0};
+	gethostname(hostname,MAX_PATH);                
+	struct hostent FAR* lpHostEnt = gethostbyname(hostname);
+	if(lpHostEnt == NULL)
+	{
+		return DEFAULT_IP;
+	}
+
+	// 取得IP地址列表中的第一个为返回的IP(因为一台主机可能会绑定多个IP)
+	LPSTR lpAddr = lpHostEnt->h_addr_list[0];      
+
+	// 将IP地址转化成字符串形式
+	struct in_addr inAddr;
+	memmove(&inAddr,lpAddr,4);
+	m_strIP = CString( inet_ntoa(inAddr) );        
+
+	return m_strIP;
+}
+
+///////////////////////////////////////////////////////////////////
+// 获得本机中处理器的数量
+int CIOCPModel::_GetNoOfProcessors()
+{
+	SYSTEM_INFO si;
+
+	GetSystemInfo(&si);
+
+	return si.dwNumberOfProcessors;
+}
+
+/////////////////////////////////////////////////////////////////////
+// 在主界面中显示提示信息
+void CIOCPModel::_ShowMessage(const CString szFormat,...) const
+{
+	// 根据传入的参数格式化字符串
+	CString   strMessage;
+	va_list   arglist;
+
+	// 处理变长参数
+	va_start(arglist, szFormat);
+	strMessage.FormatV(szFormat,arglist);
+	va_end(arglist);
+
+	// 在主界面中显示
+	CMainDlg* pMain = (CMainDlg*)m_pMain;
+	if( m_pMain!=NULL )
+	{
+		pMain->AddInformation(strMessage);
+		TRACE( strMessage+_T("\n") );
+	}	
+}
+
+/////////////////////////////////////////////////////////////////////
+// 判断客户端Socket是否已经断开,否则在一个无效的Socket上投递WSARecv操作会出现异常
+// 使用的方法是尝试向这个socket发送数据,判断这个socket调用的返回值
+// 因为如果客户端网络异常断开(例如客户端崩溃或者拔掉网线等)的时候,服务器端是无法收到客户端断开的通知的
+
+bool CIOCPModel::_IsSocketAlive(SOCKET s)
+{
+	int nByteSent=send(s,"",0,0);
+	if (-1 == nByteSent) return false;
+	return true;
+}
+
+///////////////////////////////////////////////////////////////////
+// 显示并处理完成端口上的错误
+bool CIOCPModel::HandleError( PER_SOCKET_CONTEXT *pContext,const DWORD& dwErr )
+{
+	// 如果是超时了,就再继续等吧  
+	if(WAIT_TIMEOUT == dwErr)  
+	{  	
+		// 确认客户端是否还活着...
+		if( !_IsSocketAlive( pContext->m_Socket) )
+		{
+			this->_ShowMessage( _T("检测到客户端异常退出!") );
+			this->_RemoveContext( pContext );
+			return true;
+		}
+		else
+		{
+			this->_ShowMessage( _T("网络操作超时!重试中...") );
+			return true;
+		}
+	}  
+
+	// 可能是客户端异常退出了
+	else if( ERROR_NETNAME_DELETED==dwErr )
+	{
+		this->_ShowMessage( _T("检测到客户端异常退出!") );
+		this->_RemoveContext( pContext );
+		return true;
+	}
+
+	else
+	{
+		this->_ShowMessage( _T("完成端口操作出现错误,线程退出。错误代码:%d"),dwErr );
+		return false;
+	}
+}
+
+
+
+

+ 171 - 0
AssistManager/AssistManager/PipeService.h

@@ -0,0 +1,171 @@
+#pragma once
+
+#define CONNECTING_STATE 0
+#define READING_STATE 1
+#define WRITING_STATE 2
+#define INSTANCES 4
+#define PIPE_TIMEOUT 5000
+#define BUFSIZE 4096
+
+// 命名管道在完成端口上投递的I/O操作的类型
+typedef enum _OPERATION_TYPE
+{
+    OP_ACCEPT, // Accept操作;
+    OP_SEND,   // 发送操作
+    OP_RECV,   // 接收操作
+    OP_MAX     // 上限;
+} OPERATION_TYPE;
+
+// 单个IO请求;
+typedef struct _PER_IO_CONTEXT
+{
+    OVERLAPPED m_Overlapped;
+    HANDLE m_PipeAccept;
+    OPERATION_TYPE m_OpType;
+    TCHAR chRequest[BUFSIZE];
+    DWORD cbRead;
+    TCHAR chReply[BUFSIZE];
+    DWORD cbToWrite;
+    // 管道状态;
+    DWORD dwState;
+    // IO是否在等待;
+    BOOL fPendingIO;
+    // 客户端进程窗口名称;
+    TCHAR chClientName[255];
+    // 客户端进程PID;
+    DWORD dwProcessId;
+
+    // 初始化
+    _PER_IO_CONTEXT()
+    {
+        ZeroMemory(&m_Overlapped, sizeof(m_Overlapped));
+        ZeroMemory(chRequest, BUFSIZE);
+        ZeroMemory(chReply, BUFSIZE);
+        ZeroMemory(chClientName, 255);
+        m_PipeAccept = INVALID_HANDLE_VALUE;
+        m_OpType = OP_ACCEPT;
+        fPendingIO = FALSE;
+        dwProcessId = 0;
+        dwState = 0;
+    }
+
+    // 释放掉句柄
+    ~_PER_IO_CONTEXT()
+    {
+        if (m_PipeAccept != INVALID_HANDLE_VALUE)
+        {
+            CloseHandle(m_PipeAccept);
+            m_PipeAccept = INVALID_HANDLE_VALUE;
+        }
+    }
+
+    // 重置缓冲区内容
+    void ResetBuffer()
+    {
+        ZeroMemory(chRequest, BUFSIZE);
+        ZeroMemory(chReply, BUFSIZE);
+        ZeroMemory(chClientName, 255);
+    }
+
+} PER_IO_CONTEXT, *PPER_IO_CONTEXT;
+
+//====================================================================================
+//
+//				CIOCPModel类定义
+//
+//====================================================================================
+
+// 工作者线程的线程参数
+class CIOCPModel;
+typedef struct _tagThreadParams_WORKER
+{
+    CIOCPModel *pIOCPModel; // 类指针,用于调用类中的函数
+    int nThreadNo;          // 线程编号
+
+} THREADPARAMS_WORKER, *PTHREADPARAM_WORKER;
+
+// CIOCPModel类
+class CIOCPModel
+{
+public:
+    CIOCPModel(void);
+    ~CIOCPModel(void);
+
+public:
+    // 启动服务器
+    bool Start();
+
+    //	停止服务器
+    void Stop();
+
+    // 设置主界面的指针,用于调用显示信息到界面中
+    void SetMainDlg(CDialog *p) { m_pMain = p; }
+
+protected:
+    // 初始化IOCP
+    bool _InitializeIOCP();
+
+    // 初始化Socket
+    bool _InitializeListenSocket();
+
+    // 最后释放资源
+    void _DeInitialize();
+
+    // 投递Accept请求
+    bool _PostAccept(PER_IO_CONTEXT *pAcceptIoContext);
+
+    // 投递接收数据请求
+    bool _PostRecv(PER_IO_CONTEXT *pIoContext);
+
+    // 在有客户端连入的时候,进行处理
+    bool _DoAccpet(PER_SOCKET_CONTEXT *pSocketContext, PER_IO_CONTEXT *pIoContext);
+
+    // 在有接收的数据到达的时候,进行处理
+    bool _DoRecv(PER_SOCKET_CONTEXT *pSocketContext, PER_IO_CONTEXT *pIoContext);
+
+    // 将客户端的相关信息存储到数组中
+    void _AddToContextList(PER_SOCKET_CONTEXT *pSocketContext);
+
+    // 将客户端的信息从数组中移除
+    void _RemoveContext(PER_SOCKET_CONTEXT *pSocketContext);
+
+    // 清空客户端信息
+    void _ClearContextList();
+
+    // 将句柄绑定到完成端口中
+    bool _AssociateWithIOCP(PER_SOCKET_CONTEXT *pContext);
+
+    // 处理完成端口上的错误
+    bool HandleError(PER_SOCKET_CONTEXT *pContext, const DWORD &dwErr);
+
+    // 线程函数,为IOCP请求服务的工作者线程
+    static DWORD WINAPI _WorkerThread(LPVOID lpParam);
+
+    // 获得本机的处理器数量
+    int _GetNoOfProcessors();
+
+    // 判断客户端Socket是否已经断开
+    bool _IsSocketAlive(SOCKET s);
+
+    // 在主界面中显示信息
+    void _ShowMessage(const CString szFormat, ...) const;
+
+private:
+    HANDLE m_hShutdownEvent; // 用来通知线程系统退出的事件,为了能够更好的退出线程
+
+    HANDLE m_hIOCompletionPort; // 完成端口的句柄
+
+    HANDLE *m_phWorkerThreads; // 工作者线程的句柄指针
+
+    int m_nThreads; // 生成的线程数量
+
+    CString m_strIP; // 服务器端的IP地址
+    int m_nPort;     // 服务器端的监听端口
+
+    CDialog *m_pMain; // 主界面的界面指针,用于在主界面中显示消息
+
+    CRITICAL_SECTION m_csContextList; // 用于Worker线程同步的互斥量
+
+    CArray<PER_IO_CONTEXT *> m_arrayClientContext; // 客户端Socket的Context信息
+
+};

+ 69 - 0
AssistManager/AssistManager/ReadMe.txt

@@ -0,0 +1,69 @@
+================================================================================
+    MICROSOFT 基础类库: AssistManager 项目概述
+===============================================================================
+
+应用程序向导已为您创建此 AssistManager 应用程序。此应用程序不仅演示使用 Microsoft 基础类的基本知识,而且可作为编写应用程序的起点。
+
+此文件包含组成 AssistManager 应用程序的各个文件的内容摘要。
+
+AssistManager.vcproj
+    这是使用应用程序向导生成的 VC++ 项目的主项目文件。
+    它包含有关生成文件的 Visual C++ 版本的信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
+
+AssistManager.h
+    这是应用程序的主要头文件。它包括其他项目特定的头文件(包括 Resource.h),并声明 CAssistManagerApp 应用程序类。
+
+AssistManager.cpp
+    这是包含应用程序类 CAssistManagerApp 的主要应用程序源文件。
+
+AssistManager.rc
+    这是程序使用的所有 Microsoft Windows 资源的列表。它包括 RES 子目录中存储的图标、位图和光标。此文件可以直接在 Microsoft Visual C++ 中进行编辑。项目资源位于 2052 中。
+
+res\AssistManager.ico
+    这是用作应用程序图标的图标文件。此图标包括在主要资源文件 AssistManager.rc 中。
+
+res\AssistManager.rc2
+    此文件包含不是由 Microsoft Visual C++ 编辑的资源。您应该将不可由资源编辑器编辑的所有资源放在此文件中。
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+应用程序向导创建一个对话框类:
+
+AssistManagerDlg.h,AssistManagerDlg.cpp - 对话框
+    这些文件包含 CAssistManagerDlg 类。该类定义应用程序主对话框的行为。该对话框的模板位于 AssistManager.rc 中,该文件可以在 Microsoft Visual C++ 中进行编辑。
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+其他功能:
+
+ActiveX 控件
+    应用程序包括对使用 ActiveX 控件的支持。
+
+打印及打印预览支持
+    应用程序向导已通过从 MFC 库调用 CView 类中的成员函数,生成了用于处理打印、打印设置和打印预览命令的代码。
+
+/////////////////////////////////////////////////////////////////////////////
+
+其他标准文件:
+
+StdAfx.h, StdAfx.cpp
+    这些文件用于生成名为 AssistManager.pch 的预编译头(PCH)文件和名为 StdAfx.obj 的预编译类型文件。
+
+Resource.h
+    这是标准头文件,它定义新资源 ID。
+    Microsoft Visual C++ 将读取并更新此文件。
+
+AssistManager.manifest
+	Windows XP 使用应用程序清单文件描述应用程序	对特定版本并行程序集的依赖性。加载程序使用此	信息从程序集缓存加载相应程序集或	从应用程序加载私有信息。应用程序清单可能作为	与应用程序可执行文件安装在同一文件夹中的外部 .manifest 文件包括在内以便重新发布,	也可能以资源的形式包括在该可执行文件中。
+/////////////////////////////////////////////////////////////////////////////
+
+其他注释:
+
+应用程序向导使用“TODO:”指示应添加或自定义的源代码部分。
+
+如果应用程序在共享 DLL 中使用 MFC,则将需要重新发布 MFC DLL。如果应用程序所用与操作系统的区域设置不同,则也将必须重新发布对应的本地化资源 MFC90XXX.DLL。
+有关这两个主题的详细信息,请参阅 MSDN 文档中有关重新发布 Visual C++ 应用程序的部分。
+
+/////////////////////////////////////////////////////////////////////////////

+ 21 - 0
AssistManager/AssistManager/Resource.h

@@ -0,0 +1,21 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by AssistManager.rc
+//
+#define IDR_MAINFRAME					128
+#define IDM_ABOUTBOX					0x0010
+#define IDD_ABOUTBOX					100
+#define IDS_ABOUTBOX					101
+#define IDD_ASSISTMANAGER_DIALOG				102
+
+// жÔÏóµÄÏÂÒ»×éĬÈÏÖµ
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+
+#define _APS_NEXT_RESOURCE_VALUE	129
+#define _APS_NEXT_CONTROL_VALUE		1000
+#define _APS_NEXT_SYMED_VALUE		101
+#define _APS_NEXT_COMMAND_VALUE		32771
+#endif
+#endif

BIN
AssistManager/AssistManager/res/AssistManager.ico


+ 13 - 0
AssistManager/AssistManager/res/AssistManager.rc2

@@ -0,0 +1,13 @@
+//
+// AssistManager.RC2 - Microsoft Visual C++ 不会直接编辑的资源
+//
+
+#ifdef APSTUDIO_INVOKED
+#error 此文件不能用 Microsoft Visual C++ 编辑
+#endif //APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+// 在此处添加手动编辑的资源...
+
+/////////////////////////////////////////////////////////////////////////////

+ 8 - 0
AssistManager/AssistManager/stdafx.cpp

@@ -0,0 +1,8 @@
+
+// stdafx.cpp : 只包括标准包含文件的源文件
+// AssistManager.pch 将作为预编译头
+// stdafx.obj 将包含预编译类型信息
+
+#include "stdafx.h"
+
+

+ 60 - 0
AssistManager/AssistManager/stdafx.h

@@ -0,0 +1,60 @@
+
+// stdafx.h : 标准系统包含文件的包含文件,
+// 或是经常使用但不常更改的
+// 特定于项目的包含文件
+
+#pragma once
+
+#ifndef _SECURE_ATL
+#define _SECURE_ATL 1
+#endif
+
+#ifndef VC_EXTRALEAN
+#define VC_EXTRALEAN            // 从 Windows 头中排除极少使用的资料
+#endif
+
+#include "targetver.h"
+
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS      // 某些 CString 构造函数将是显式的
+
+// 关闭 MFC 对某些常见但经常可放心忽略的警告消息的隐藏
+#define _AFX_ALL_WARNINGS
+
+#include <afxwin.h>         // MFC 核心组件和标准组件
+#include <afxext.h>         // MFC 扩展
+
+
+#include <afxdisp.h>        // MFC 自动化类
+
+
+
+#ifndef _AFX_NO_OLE_SUPPORT
+#include <afxdtctl.h>           // MFC 对 Internet Explorer 4 公共控件的支持
+#endif
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h>             // MFC 对 Windows 公共控件的支持
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+#include <afxcontrolbars.h>     // 功能区和控件条的 MFC 支持
+
+
+
+
+
+
+
+
+
+#ifdef _UNICODE
+#if defined _M_IX86
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_IA64
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_X64
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#else
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#endif
+#endif
+
+

+ 26 - 0
AssistManager/AssistManager/targetver.h

@@ -0,0 +1,26 @@
+
+#pragma once
+
+// 以下宏定义要求的最低平台。要求的最低平台
+// 是具有运行应用程序所需功能的 Windows、Internet Explorer 等产品的
+// 最早版本。通过在指定版本及更低版本的平台上启用所有可用的功能,宏可以
+// 正常工作。
+
+// 如果必须要针对低于以下指定版本的平台,请修改下列定义。
+// 有关不同平台对应值的最新信息,请参考 MSDN。
+#ifndef WINVER                          // 指定要求的最低平台是 Windows Vista。
+#define WINVER 0x0600           // 将此值更改为相应的值,以适用于 Windows 的其他版本。
+#endif
+
+#ifndef _WIN32_WINNT            // 指定要求的最低平台是 Windows Vista。
+#define _WIN32_WINNT 0x0600     // 将此值更改为相应的值,以适用于 Windows 的其他版本。
+#endif
+
+#ifndef _WIN32_WINDOWS          // 指定要求的最低平台是 Windows 98。
+#define _WIN32_WINDOWS 0x0410 // 将此值更改为适当的值,以适用于 Windows Me 或更高版本。
+#endif
+
+#ifndef _WIN32_IE                       // 指定要求的最低平台是 Internet Explorer 7.0。
+#define _WIN32_IE 0x0700        // 将此值更改为相应的值,以适用于 IE 的其他版本。
+#endif
+