Restructure repository to include all source folders

Move git root from Client/ to src/ to track all source code:
- Client: Game client source (moved to Client/Client/)
- Server: Game server source
- GameTools: Development tools
- CryptoSource: Encryption utilities
- database: Database scripts
- Script: Game scripts
- rylCoder_16.02.2008_src: Legacy coder tools
- GMFont, Game: Additional resources

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-29 20:17:20 +09:00
parent 5d3cd64a25
commit dd97ddec92
11602 changed files with 1446576 additions and 0 deletions

Binary file not shown.

View File

@@ -0,0 +1,76 @@
// ChatParser.cpp : 응용 프로그램에 대한 클래스 동작을 정의합니다.
//
#include "stdafx.h"
#include "ChatParser.h"
#include "ChatParserDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CChatParserApp
BEGIN_MESSAGE_MAP(CChatParserApp, CWinApp)
ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()
// CChatParserApp 생성
CChatParserApp::CChatParserApp()
{
// TODO: 여기에 생성 코드를 추가합니다.
// InitInstance에 모든 중요한 초기화 작업을 배치합니다.
}
// 유일한 CChatParserApp 개체입니다.
CChatParserApp theApp;
// CChatParserApp 초기화
BOOL CChatParserApp::InitInstance()
{
// 응용 프로그램 매니페스트가 ComCtl32.dll 버전 6 이상을 사용하여 비주얼 스타일을
// 사용하도록 지정하는 경우, Windows XP 상에서 반드시 InitCommonControlsEx()가 필요합니다.
// InitCommonControlsEx()를 사용하지 않으면 창을 만들 수 없습니다.
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// 응용 프로그램에서 사용할 모든 공용 컨트롤 클래스를 포함하도록
// 이 항목을 설정하십시오.
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinApp::InitInstance();
// 표준 초기화
// 이들 기능을 사용하지 않고 최종 실행 파일의 크기를 줄이려면
// 아래에서 필요 없는 특정 초기화
// 루틴을 제거해야 합니다.
// 해당 설정이 저장된 레지스트리 키를 변경하십시오.
// TODO: 이 문자열을 회사 또는 조직의 이름과 같은
// 적절한 내용으로 수정해야 합니다.
SetRegistryKey(_T("로컬 응용 프로그램 마법사에서 생성된 응용 프로그램"));
CChatParserDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: 여기에 [확인]을 클릭하여 대화 상자가 없어질 때 처리할
// 코드를 배치합니다.
}
else if (nResponse == IDCANCEL)
{
// TODO: 여기에 [취소]를 클릭하여 대화 상자가 없어질 때 처리할
// 코드를 배치합니다.
}
// 대화 상자가 닫혔으므로 응용 프로그램의 메시지 펌프를 시작하지 않고 응용 프로그램을 끝낼 수 있도록 FALSE를
// 반환합니다.
return FALSE;
}

View File

@@ -0,0 +1,31 @@
// ChatParser.h : PROJECT_NAME 응용 프로그램에 대한 주 헤더 파일입니다.
//
#pragma once
#ifndef __AFXWIN_H__
#error "PCH에 대해 이 파일을 포함하기 전에 'stdafx.h'를 포함합니다."
#endif
#include "resource.h" // 주 기호입니다.
// CChatParserApp:
// 이 클래스의 구현에 대해서는 ChatParser.cpp을 참조하십시오.
//
class CChatParserApp : public CWinApp
{
public:
CChatParserApp();
// 재정의입니다.
public:
virtual BOOL InitInstance();
// 구현입니다.
DECLARE_MESSAGE_MAP()
};
extern CChatParserApp theApp;

View File

@@ -0,0 +1,204 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// 한국어 resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_KOR)
#ifdef _WIN32
LANGUAGE LANG_KOREAN, SUBLANG_DEFAULT
#pragma code_page(949)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#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_KOR)\r\n"
"LANGUAGE 18, 1\r\n"
"#pragma code_page(949)\r\n"
"#include ""res\\ChatParser.rc2"" // Microsoft Visual C++ 이외의 다른 도구에서 편집한 리소스입니다.\r\n"
"#include ""afxres.rc"" // 표준 구성 요소입니다.\r\n"
"#endif\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDR_MAINFRAME ICON "res\\ChatParser.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_ABOUTBOX DIALOGEX 0, 0, 235, 55
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "ChatParser 정보"
FONT 9, "MS 셸 대화 상자", 0, 0, 0x1
BEGIN
ICON IDR_MAINFRAME,IDC_STATIC,11,17,20,20
LTEXT "ChatParser 버전 1.0",IDC_STATIC,40,10,119,8,SS_NOPREFIX
LTEXT "Copyright (C) 2008",IDC_STATIC,40,25,119,8
DEFPUSHBUTTON "확인",IDOK,178,7,50,16,WS_GROUP
END
IDD_CHATPARSER_DIALOG DIALOGEX 0, 0, 499, 399
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_APPWINDOW
CAPTION "ChatParser"
FONT 9, "굴림", 400, 0, 0x81
BEGIN
PUSHBUTTON "Open",IDC_OPENFILE,433,7,59,14
CONTROL "Oldversion",IDC_OLDVERSION,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,443,25,49,10
LISTBOX IDC_CHATLIST,7,40,485,352,LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP
EDITTEXT IDC_OPEN_FILENAME,7,7,423,14,ES_AUTOHSCROLL | ES_READONLY
COMBOBOX IDC_SERVERID,7,24,52,102,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_ZONEID,61,24,48,124,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "find",IDC_FINDLIST,359,23,59,14
COMBOBOX IDC_CHATTYPE,111,24,103,124,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
EDITTEXT IDC_FINDNAME,216,24,86,13,ES_AUTOHSCROLL
CONTROL "FindName",IDC_FINDNAMECHK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,304,26,55,10
END
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
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 "041203b5"
BEGIN
VALUE "CompanyName", "TODO: <회사 이름>"
VALUE "FileDescription", "TODO: <파일 설명>"
VALUE "FileVersion", "1.0.0.1"
VALUE "InternalName", "ChatParser.exe"
VALUE "LegalCopyright", "TODO: (c) <회사 이름>. All rights reserved."
VALUE "OriginalFilename", "ChatParser.exe"
VALUE "ProductName", "TODO: <제품 이름>"
VALUE "ProductVersion", "1.0.0.1"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x412, 949
END
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_ABOUTBOX, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 228
TOPMARGIN, 7
BOTTOMMARGIN, 48
END
IDD_CHATPARSER_DIALOG, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 492
TOPMARGIN, 7
BOTTOMMARGIN, 392
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE
BEGIN
IDS_ABOUTBOX "ChatParser 정보(&A)..."
END
#endif // 한국어 resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
#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_KOR)
LANGUAGE 18, 1
#pragma code_page(949)
#include "res\ChatParser.rc2" // Microsoft Visual C++ 이외의 다른 도구에서 편집한 리소스입니다.
#include "afxres.rc" // 표준 구성 요소입니다.
#endif
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ChatParser", "ChatParser.vcproj", "{380483B5-D873-4836-9D31-99C0791A6F4F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{380483B5-D873-4836-9D31-99C0791A6F4F}.Debug|Win32.ActiveCfg = Debug|Win32
{380483B5-D873-4836-9D31-99C0791A6F4F}.Debug|Win32.Build.0 = Debug|Win32
{380483B5-D873-4836-9D31-99C0791A6F4F}.Release|Win32.ActiveCfg = Release|Win32
{380483B5-D873-4836-9D31-99C0791A6F4F}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

Binary file not shown.

View File

@@ -0,0 +1,311 @@
<?xml version="1.0" encoding="ks_c_5601-1987"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="ChatParser"
ProjectGUID="{380483B5-D873-4836-9D31-99C0791A6F4F}"
RootNamespace="ChatParser"
Keyword="MFCProj"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
UseOfMFC="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="_DEBUG"
MkTypLibCompatible="false"
ValidateParameters="false"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_WINDOWS;_DEBUG"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="2"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="_DEBUG"
Culture="1042"
AdditionalIncludeDirectories="$(IntDir)"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
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="1"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="false"
ValidateParameters="false"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;_WINDOWS;NDEBUG"
MinimalRebuild="false"
RuntimeLibrary="0"
UsePrecompiledHeader="2"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="1042"
AdditionalIncludeDirectories="$(IntDir)"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
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=".\ChatParser.cpp"
>
</File>
<File
RelativePath=".\ChatParserDlg.cpp"
>
</File>
<File
RelativePath=".\ChatParserSetup.cpp"
>
</File>
<File
RelativePath=".\Clipboard.cpp"
>
</File>
<File
RelativePath=".\NFTokenizer.cpp"
>
</File>
<File
RelativePath=".\RegFunctions.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>
<File
RelativePath=".\XListBox.cpp"
>
</File>
</Filter>
<Filter
Name="헤더 파일"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\ChatParser.h"
>
</File>
<File
RelativePath=".\ChatParserDlg.h"
>
</File>
<File
RelativePath=".\ChatParserSetup.h"
>
</File>
<File
RelativePath=".\Clipboard.h"
>
</File>
<File
RelativePath=".\NFTokenizer.h"
>
</File>
<File
RelativePath=".\RegFunctions.h"
>
</File>
<File
RelativePath=".\Resource.h"
>
</File>
<File
RelativePath=".\stdafx.h"
>
</File>
<File
RelativePath=".\XListBox.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\ChatParser.ico"
>
</File>
<File
RelativePath=".\ChatParser.rc"
>
</File>
<File
RelativePath=".\res\ChatParser.rc2"
>
</File>
</Filter>
<File
RelativePath=".\ReadMe.txt"
>
</File>
</Files>
<Globals>
<Global
Name="RESOURCE_FILE"
Value="ChatParser.rc"
/>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,564 @@
// ChatParserDlg.cpp : 구현 파일
//
#include "stdafx.h"
#include "ChatParser.h"
#include "ChatParserDlg.h"
#include "NFTokenizer.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()
// CChatParserDlg 대화 상자
CChatParserDlg::CChatParserDlg(CWnd* pParent /*=NULL*/)
: CDialog(CChatParserDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CChatParserDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_CHATLIST, m_ChatList);
DDX_Control(pDX, IDC_OLDVERSION, m_OldVersion);
DDX_Control(pDX, IDC_SERVERID, m_ServerGroup);
DDX_Control(pDX, IDC_ZONEID, m_ServerZone);
DDX_Control(pDX, IDC_CHATTYPE, m_ChatType);
DDX_Control(pDX, IDC_FINDNAMECHK, m_FindNameChk);
DDX_Control(pDX, IDC_FINDNAME, m_FindName);
}
BEGIN_MESSAGE_MAP(CChatParserDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDC_OPENFILE, &CChatParserDlg::OnBnClickedOpenfile)
ON_BN_CLICKED(IDC_FINDLIST, &CChatParserDlg::OnBnClickedFindlist)
ON_BN_CLICKED(IDC_FINDNAMECHK, &CChatParserDlg::OnBnClickedFindnamechk)
END_MESSAGE_MAP()
// CChatParserDlg 메시지 처리기
BOOL CChatParserDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// 시스템 메뉴에 "정보..." 메뉴 항목을 추가합니다.
// IDM_ABOUTBOX는 시스템 명령 범위에 있어야 합니다.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 이 대화 상자의 아이콘을 설정합니다. 응용 프로그램의 주 창이 대화 상자가 아닐 경우에는
// 프레임워크가 이 작업을 자동으로 수행합니다.
SetIcon(m_hIcon, TRUE); // 큰 아이콘을 설정합니다.
SetIcon(m_hIcon, FALSE); // 작은 아이콘을 설정합니다.
// TODO: 여기에 추가 초기화 작업을 추가합니다.
SetDlgItemText(IDC_OPENFILE, GetMyINIString("LOCAL_STRING", "STRING_01"));
SetDlgItemText(IDC_OLDVERSION, GetMyINIString("LOCAL_STRING", "STRING_02"));
SetDlgItemText(IDC_FINDLIST, GetMyINIString("LOCAL_STRING", "STRING_04"));
SetDlgItemText(IDC_FINDNAMECHK, GetMyINIString("LOCAL_STRING", "STRING_05"));
m_FindName.EnableWindow(FALSE);
int iCount = atoi(GetMyINIString("SERVER_GROUP", "SERVER_GROUP_CNT"));
char strID[32];
char strName[32];
m_ServerGroup.AddString("All");
for(int i = 0; i < iCount; ++i)
{
wsprintf(strID, "SERVER_GROUP%d", i+1);
m_ServerGroup.AddString(GetMyINIString("SERVER_GROUP", strID));
}
m_ServerGroup.SetCurSel(0);
iCount = atoi(GetMyINIString("SERVER_ZONE", "SERVER_ZONE_CNT"));
m_ServerZone.AddString("All");
for(int i = 0; i < iCount; ++i)
{
wsprintf(strID, "SERVER_ZONE%d", i+1);
wsprintf(strName, "ZONE%s", GetMyINIString("SERVER_ZONE", strID));
m_ServerZone.AddString(strName);
}
m_ServerZone.SetCurSel(0);
iCount = atoi(GetMyINIString("CHAT_TYPE", "CHAT_TYPE_CNT"));
m_ChatType.AddString("All");
for(int i = 0; i < iCount; ++i)
{
wsprintf(strID, "CHAT_TYPE%d", i+1);
m_ChatType.AddString(GetMyINIString("CHAT_TYPE", strID));
}
m_ChatType.SetCurSel(0);
memset(&m_OpenFile, 0, sizeof(OPENFILENAME));
m_OpenFile.lStructSize = sizeof(OPENFILENAME);
m_OpenFile.hwndOwner = m_hWnd;
m_OpenFile.lpstrFilter = "Chat Log files\0*.log\0All files\0*.*";
m_OpenFile.nMaxFile = MAX_PATH * MAX_PATH;
m_OpenFile.Flags = OFN_FILEMUSTEXIST | OFN_LONGNAMES | OFN_EXPLORER;
m_OpenFile.lpstrFile = m_szFileName;
return TRUE; // 포커스를 컨트롤에 설정하지 않으면 TRUE를 반환합니다.
}
void CChatParserDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// 대화 상자에 최소화 단추를 추가할 경우 아이콘을 그리려면
// 아래 코드가 필요합니다. 문서/뷰 모델을 사용하는 MFC 응용 프로그램의 경우에는
// 프레임워크에서 이 작업을 자동으로 수행합니다.
void CChatParserDlg::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 CChatParserDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
// 추가
void CChatParserDlg::AddLineToChatList(unsigned char cChatType, char* szMsg)
{
CXListBox::Color cBackColor = CXListBox::BackColor;
CXListBox::Color cMessageColor = CXListBox::ChatNormal;
switch(cChatType)
{
case NORMAL:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatNormal;
break;
case PARTY:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatParty;
break;
case FRIEND:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatFriend;
break;
case GUILD:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatGuild;
break;
case CLIENT_LOG:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatNormal;
break;
case STALL:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatStall;
break;
case SHOUT:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatShout;
break;
case ADMIN_NORMAL_CHAT:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatAdminNormal;
break;
case ADMIN_SHOUT:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatAdminShout;
break;
case WHISPER:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatWhisper;
break;
case TRADE:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatTrade;
break;
case NOTICE:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatNotice;
break;
case DICE:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::ChatAdminShout;
break;
case GMREPORT:
cBackColor = CXListBox::BackColor; cMessageColor = CXListBox::GMReport;
break;
}
m_ChatList.AddLine(cMessageColor, cBackColor, szMsg, FALSE);
}
void CChatParserDlg::Cleanup()
{
m_ChatList.ResetContent();
}
void CChatParserDlg::OnBnClickedOpenfile()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
ZeroMemory(m_szFileName, MAX_PATH);
if(GetOpenFileName(&m_OpenFile))
{
// 파서하기
LoadFile();
SetDlgItemText(IDC_OPEN_FILENAME, m_szFileName);
}
}
void CChatParserDlg::LoadFile()
{
FILE* fp = fopen(m_szFileName, "rt");
if(fp == NULL)
return;
Cleanup();
m_ChatData.clear();
int iCount = 0;
BOOL bOldVersion = FALSE;
if(m_OldVersion.GetCheck())
bOldVersion = TRUE;
char strData[2048];
int Len = 0;
CHATLIST st;
while(!feof(fp))
{
fgets(strData, 2048, fp);
if(strncmp(strData, "[Ty-NOR]", 8) == 0)
break;
else
{
std::string str = strData;
std::string temp, temp2;
Nave::NFTokenizerA token(str, "[");
int iToken = token.CountTokens();
DWORD dwServerID = 0;
int Temp = 0;
for(int i = 0; i < iToken; ++i)
{
temp = token.NextToken();
if(i == 0) // 시간
{
sscanf(temp.c_str(), "%04d-%02d-%02d %02d:%02d:%02d",
&st.sysTime.wYear, &st.sysTime.wMonth, &st.sysTime.wDay,
&st.sysTime.wHour, &st.sysTime.wMinute, &st.sysTime.wSecond);
}
else if(i == 1)
{
sscanf(temp.c_str(), "ServerID:0x%08x", &dwServerID);
}
else if(i == 2)
{
temp2 = &temp[6];
temp2.erase(temp2.end()-1);
int n = temp2.find_first_of(" ");
strcpy(st.strServerName, temp2.c_str());
st.strServerName[n] = 0;
}
else if(i == 3)
{
sscanf(temp.c_str(), "Zone:%2d", &st.iZone);
}
else if(i == 4)
{
sscanf(temp.c_str(), "CH:%2d", &st.iChannel);
}
else if(i == 5)
{
sscanf(temp.c_str(), "X:%4d", &Temp);
}
else if(i == 6)
{
sscanf(temp.c_str(), "Z:%4d", &Temp);
}
else if(i == 7)
{
sscanf(temp.c_str(), "UID:%10d", &st.dwUID);
}
else if(i == 8)
{
sscanf(temp.c_str(), "CID:%10d", &st.dwCID);
}
else if(i == 9)
{
sscanf(temp.c_str(), "Type:%2d", &st.iChatType);
}
else if(i == 10)
{
temp2 = &temp[2];
temp2.erase(temp2.end()-1);
int n = temp2.find_last_not_of(" ");
strcpy(st.strSenderName, temp2.c_str());
st.strSenderName[n+1] = 0;
}
else if(i == 11)
{
temp2 = &temp[2];
temp2.erase(temp2.end()-1);
int n = temp2.find_last_not_of(" ");
strcpy(st.strTargetName, temp2.c_str());
st.strTargetName[n+1] = 0;
}
else if(i == 12)
{
strncpy(st.strMessage, temp.c_str(), temp.size()-2);
st.strMessage[temp.size()-2] = 0;
}
}
m_ChatData[iCount++] = st;
}
/*
if(strncmp(strData, "[Ty-NOR]", 8) == 0)
break;
else
{
// 시간 읽기
sscanf(strData, "[%04d-%02d-%02d %02d:%02d:%02d]",
&st.sysTime.wYear, &st.sysTime.wMonth, &st.sysTime.wDay,
&st.sysTime.wHour, &st.sysTime.wMinute, &st.sysTime.wSecond);
// 그룹
sscanf(&strData[21], "[Group:%s]", st.strServerName);
// 아이디들
sscanf(&strData[44], "[Zone:%2d][CH:%2d][UID:%10d][CID:%10d][Type:%2d]", &st.iZone, &st.iChannel, &st.dwUID, &st.dwCID, &st.iChatType);
if(strncmp(&strData[101], "[S:", 3) == 0)
{
// Sender
sscanf(&strData[101], "[S:%s]", st.strSenderName);
// Target
sscanfe(&strData[120], "[T:%s]", st.strTargetName);
if(st.strTargetName[0] == ']')
ZeroMemory(st.strTargetName, 32);
// Msg
strcpy(st.strMessage, &strData[140]);
Len = (int)strlen(st.strMessage);
if(st.strMessage[Len-2] == ']')
st.strMessage[Len-2] = 0;
else
st.strMessage[Len-1] = 0;
}
else
{
// Msg
strcpy(st.strMessage, &strData[102]);
Len = (int)strlen(st.strMessage);
if(st.strMessage[Len-2] == ']')
st.strMessage[Len-2] = 0;
else
st.strMessage[Len-1] = 0;
}
m_ChatData[iCount++] = st;
}
*/
}
m_ChatList.AddString(GetMyINIString("LOCAL_STRING", "STRING_03"));
fclose(fp);
}
void CChatParserDlg::OnBnClickedFindlist()
{
// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
Cleanup();
char strData[2048];
int Len = 0;
char strTemp[32];
char strServerGroup[32];
int iGroupID = m_ServerGroup.GetCurSel();
if(iGroupID != 0)
{
m_ServerGroup.GetWindowText(strServerGroup, 32);
}
int iZoneID = m_ServerZone.GetCurSel();
if(iZoneID != 0)
{
iZoneID = 0;
m_ServerZone.GetWindowText(strTemp, 32);
sscanf(strTemp, "ZONE%d", &iZoneID);
}
int iChatType = m_ChatType.GetCurSel();
if(iChatType != 0)
{
m_ChatType.GetWindowText(strTemp, 32);
iChatType = GetChatType(strTemp);
}
char strName[64];
BOOL bFindName = FALSE;
if(m_FindNameChk.GetCheck())
{
bFindName = TRUE;
m_FindName.GetWindowText(strName, 64);
}
else
{
ZeroMemory(strName, 64);
}
// 출력
std::map<int, CHATLIST>::iterator obj = m_ChatData.begin();
std::map<int, CHATLIST>::iterator end = m_ChatData.end();
BOOL bAddItem;
while(obj != end)
{
CHATLIST& st = obj->second;
bAddItem = TRUE;
if(iGroupID != 0 && strcmp(strServerGroup, st.strServerName) != 0)
{
bAddItem = FALSE;
}
if(iZoneID != 0 && st.iZone != iZoneID)
{
bAddItem = FALSE;
}
if(iChatType != 0 && st.iChatType != iChatType)
{
bAddItem = FALSE;
}
if(bFindName)
{
if(strcmp(strName, st.strSenderName) != 0 && strcmp(strName, st.strTargetName) != 0)
bAddItem = FALSE;
}
if(bAddItem)
{
if(st.iChatType-1 == WHISPER)
{
if(strlen(st.strTargetName) == 0)
wsprintf(strData, "%-15s[Z:%02d/C:%d][%02d:%02d] %s", st.strServerName, st.iZone, st.iChannel, st.sysTime.wHour, st.sysTime.wMinute, st.strMessage);
else
wsprintf(strData, "%-15s[Z:%02d/C:%d][%02d:%02d] %s (To: %s)", st.strServerName, st.iZone, st.iChannel, st.sysTime.wHour, st.sysTime.wMinute, st.strMessage, st.strTargetName);
}
else
{
wsprintf(strData, "%-15s[Z:%02d/C:%d][%02d:%02d] %s", st.strServerName, st.iZone, st.iChannel, st.sysTime.wHour, st.sysTime.wMinute, st.strMessage);
}
if(iChatType == 0)
AddLineToChatList(st.iChatType-1, strData);
else
AddLineToChatList(iChatType-1, strData);
}
++obj;
}
UpdateData(false);
}
void CChatParserDlg::OnBnClickedFindnamechk()
{
m_FindName.EnableWindow(m_FindNameChk.GetCheck());
}

View File

@@ -0,0 +1,92 @@
// ChatParserDlg.h : 헤더 파일
//
#pragma once
#include "afxwin.h"
#include "XListBox.h"
#include <map>
typedef struct CHATLIST
{
SYSTEMTIME sysTime;
char strServerName[32];
int iZone;
int iChannel;
unsigned long dwUID;
unsigned long dwCID;
int iChatType;
char strSenderName[32];
char strTargetName[32];
char strMessage[512];
CHATLIST()
{
Clear();
}
void Clear()
{
ZeroMemory(&sysTime, sizeof(sysTime));
iZone=0;
iChannel=0;
dwUID=0;
dwCID=0;
iChatType=0;
ZeroMemory(strServerName, 32);
ZeroMemory(strSenderName, 32);
ZeroMemory(strTargetName, 32);
ZeroMemory(strMessage, 512);
}
}CHATLIST;
// CChatParserDlg 대화 상자
class CChatParserDlg : public CDialog
{
// 생성입니다.
public:
CChatParserDlg(CWnd* pParent = NULL); // 표준 생성자입니다.
// 대화 상자 데이터입니다.
enum { IDD = IDD_CHATPARSER_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 지원입니다.
void AddLineToChatList(unsigned char cChatType, char* szMsg);
void Cleanup();
void LoadFile();
// 구현입니다.
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()
public:
OPENFILENAME m_OpenFile;
char m_szFileName[MAX_PATH * MAX_PATH];
std::map<int, CHATLIST> m_ChatData;
CXListBox m_ChatList;
CButton m_OldVersion;
CComboBox m_ServerGroup;
CComboBox m_ServerZone;
CComboBox m_ChatType;
CButton m_FindNameChk;
CEdit m_FindName;
public:
afx_msg void OnBnClickedOpenfile();
afx_msg void OnBnClickedFindlist();
afx_msg void OnBnClickedFindnamechk();
};

View File

@@ -0,0 +1,15 @@
#include "stdafx.h"
#include "ChatParserSetup.h"
CChatParserSetup::CChatParserSetup(const char* szFileName)
: Registry::CSetupFile(szFileName)
{
}
CChatParserSetup& CChatParserSetup::GetInstance()
{
static CChatParserSetup setup("./ChatParserSetup.ini");
return setup;
}

View File

@@ -0,0 +1,17 @@
#ifndef _GAMA_NETWORK_CHAT_SETUP_H_
#define _GAMA_NETWORK_CHAT_SETUP_H_
#include "RegFunctions.h"
/** \class CChatParserSetup
모니터링 툴 셋업 클래스*/
class CChatParserSetup : public Registry::CSetupFile
{
public:
CChatParserSetup(const char* szFileName);
static CChatParserSetup& GetInstance();
};
#endif

View File

@@ -0,0 +1,42 @@
[SERVER_GROUP]
SERVER_GROUP_CNT = 1
SERVER_GROUP1 = Ichman
[SERVER_ZONE]
SERVER_ZONE_CNT = 9
SERVER_ZONE1 = 1
SERVER_ZONE2 = 2
SERVER_ZONE3 = 4
SERVER_ZONE4 = 5
SERVER_ZONE5 = 8
SERVER_ZONE6 = 12
SERVER_ZONE7 = 16
SERVER_ZONE8 = 17
SERVER_ZONE9 = 18
[CHAT_TYPE]
CHAT_TYPE_CNT = 17
CHAT_TYPE1 = NORMAL
CHAT_TYPE2 = PARTY
CHAT_TYPE3 = FRIEND
CHAT_TYPE4 = GUILD
CHAT_TYPE5 = CLIENT_LOG
CHAT_TYPE6 = STALL
CHAT_TYPE7 = SHOUT
CHAT_TYPE8 = ADMIN_NORMAL_CHAT
CHAT_TYPE9 = ADMIN_SHOUT
CHAT_TYPE10 = WHISPER
CHAT_TYPE11 = TRADE
CHAT_TYPE12 = CAMP_SHOP
CHAT_TYPE13 = NOTIFY_CHAR_INFO
CHAT_TYPE14 = FIND_PARTY
CHAT_TYPE15 = ENEMY_CHECK
CHAT_TYPE16 = DICE
CHAT_TYPE17 = NOTICE
[LOCAL_STRING]
STRING_01 = 열기
STRING_02 = 구버젼 로그
STRING_03 = 로딩 완료.
STRING_04 = 검색
STRING_05 = 이름검색

View File

@@ -0,0 +1,253 @@
// CClipboard Class
// ----------------
// Written by David Terracino <davet@lycosemail.com>
//
// This code is released into the public domain, because
// it's silly easy. If you want to use and expand it, go
// ahead; fine by me. If you do expand this class's
// functionality, please consider sending it back up to
// the MFC Programmer's Sourcebook at www.codeguru.com.
//
// And as always, please give credit where credit is
// due. Don't remove my name from the source.
///////////////////////////////////////////////////////////////////////////////
// Modified by Hans Dietrich hdietrich2@hotmail.com
///////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Clipboard.h"
///////////////////////////////////////////////////////////////////////////////
// GetText - Retrieves text from the clipboard
///////////////////////////////////////////////////////////////////////////////
//
// Parameters:
//
// Return Values:
// CString - not empty if text was successfully copied from clipboard
//
///////////////////////////////////////////////////////////////////////////////
CString CClipboard::GetText()
{
CString str;
str = _T("");
// First, open the clipboard. OpenClipboard() takes one
// parameter, the handle of the window that will temporarily
// be it's owner. If NULL is passed, the current process
// is assumed.
if (::OpenClipboard(NULL))
{
// Request a pointer to the text on the clipboard.
HGLOBAL hGlobal = ::GetClipboardData(CF_TEXT);
// If there was no text on the clipboard, we have
// been returned a NULL handle.
if (hGlobal)
{
// Now we have a global memory handle to the text
// stored on the clipboard. We have to lock this global
// handle so that we have access to it.
LPSTR lpszData = (LPSTR) ::GlobalLock(hGlobal);
if (lpszData)
{
str = lpszData;
// Now, simply unlock the global memory pointer
// and close the clipboard.
::GlobalUnlock(hGlobal);
}
}
::CloseClipboard();
}
return str;
}
///////////////////////////////////////////////////////////////////////////////
// GetText - Retrieves text from the clipboard
///////////////////////////////////////////////////////////////////////////////
//
// Parameters:
// lpszBuffer - pointer to a string where the text is to be put
// nBufSize - allocated length of lpszBuffer
//
// Return Values:
// TRUE - Text was successfully retrieved
// FALSE - No text returned
//
///////////////////////////////////////////////////////////////////////////////
BOOL CClipboard::GetText(LPSTR lpszBuffer, int nBufSize)
{
ASSERT(lpszBuffer);
if (lpszBuffer == NULL)
return FALSE;
if (nBufSize == 0)
return FALSE;
lpszBuffer[0] = 0;
BOOL bSuccess = FALSE;
// First, open the clipboard. OpenClipboard() takes one
// parameter, the handle of the window that will temporarily
// be it's owner. If NULL is passed, the current process
// is assumed.
if (::OpenClipboard(NULL))
{
// Request a pointer to the text on the clipboard.
HGLOBAL hGlobal = ::GetClipboardData(CF_TEXT);
// If there was no text on the clipboard, we have
// been returned a NULL handle.
if (hGlobal)
{
// Now we have a global memory handle to the text
// stored on the clipboard. We have to lock this global
// handle so that we have access to it.
LPSTR lpszData = (LPSTR) ::GlobalLock(hGlobal);
if (lpszData)
{
// Now get the size of the text on the clipboard.
DWORD nSize = (DWORD)::GlobalSize(hGlobal);
// Make sure the text on the clipboard is not longer
// that the buffer that was allocated for it. If it was
// snip the text on the clipboard so that it fits.
if (nSize >= (UINT)nBufSize)
nSize = nBufSize - 1;
// Now, copy the text into the return buffer. Note that
// there will be at least one nul at the end
ZeroMemory(lpszBuffer, nBufSize);
CopyMemory(lpszBuffer, lpszData, nSize);
// Now, simply unlock the global memory pointer
// and close the clipboard.
::GlobalUnlock(hGlobal);
bSuccess = TRUE;
}
}
::CloseClipboard();
}
return bSuccess;
}
///////////////////////////////////////////////////////////////////////////////
// GetTextLength - Retrieves length of text on the clipboard
///////////////////////////////////////////////////////////////////////////////
//
// Parameters:
//
// Return Values:
// > 0 - Text length was successfully returned.
// 0 - No text on the clipboard
//
///////////////////////////////////////////////////////////////////////////////
DWORD CClipboard::GetTextLength()
{
DWORD nSize = 0; // Size of clipboard data
// First, open the clipboard. OpenClipboard() takes one
// parameter, the handle of the window that will temporarily
// be it's owner. If NULL is passed, the current process
// is assumed.
if (::OpenClipboard(NULL))
{
// Request a pointer to the text on the clipboard.
HGLOBAL hGlobal = ::GetClipboardData(CF_TEXT);
// If there was no text on the clipboard, we have
// been returned a NULL handle.
if (hGlobal)
{
// Now we have a global memory handle to the text
// stored on the clipboard. We have to lock this global
// handle so that we have access to it.
LPSTR lpszData = (LPSTR) ::GlobalLock(hGlobal);
if (lpszData)
{
// Now get the size of the text on the clipboard.
nSize = (DWORD)::GlobalSize(hGlobal);
// Now, simply unlock the global memory pointer
// and close the clipboard.
::GlobalUnlock(hGlobal);
}
}
::CloseClipboard();
}
return nSize;
}
///////////////////////////////////////////////////////////////////////////////
// SetText - Places text on the clipboard
///////////////////////////////////////////////////////////////////////////////
//
// Parameters:
// lpszBuffer - pointer to a string to put on the clipboard
//
// Return Values:
// TRUE - Text was successfully copied onto clipboard
// FALSE - Text not copied
//
///////////////////////////////////////////////////////////////////////////////
BOOL CClipboard::SetText(LPCTSTR lpszBuffer)
{
BOOL bSuccess = FALSE;
// First, open the clipboard. OpenClipboard() takes one
// parameter, the handle of the window that will temporarily
// be it's owner. If NULL is passed, the current process
// is assumed. After opening, empty the clipboard so we
// can put our text on it.
if (::OpenClipboard(NULL))
{
::EmptyClipboard();
// Get the size of the string in the buffer that was
// passed into the function, so we know how much global
// memory to allocate for the string.
int nSize = (int)_tcslen(lpszBuffer);
// Allocate the memory for the string.
HGLOBAL hGlobal = ::GlobalAlloc(GMEM_ZEROINIT, nSize+1);
// If we got any error during the memory allocation,
// we have been returned a NULL handle.
if (hGlobal)
{
// Now we have a global memory handle to the text
// stored on the clipboard. We have to lock this global
// handle so that we have access to it.
LPTSTR lpszData = (LPTSTR) ::GlobalLock(hGlobal);
if (lpszData)
{
// Now, copy the text from the buffer into the allocated
// global memory pointer
_tcscpy(lpszData, lpszBuffer);
// Now, simply unlock the global memory pointer,
// set the clipboard data type and pointer,
// and close the clipboard.
::GlobalUnlock(hGlobal);
::SetClipboardData(CF_TEXT, hGlobal);
bSuccess = TRUE;
}
}
::CloseClipboard();
}
return bSuccess;
}

View File

@@ -0,0 +1,29 @@
// CClipboard Class
// ----------------
// Written by David Terracino <davet@lycosemail.com>
//
// This code is released into the public domain, because
// it's silly easy. If you want to use and expand it, go
// ahead; fine by me. If you do expand this class's
// functionality, please consider sending it back up to
// the MFC Programmer's Sourcebook at www.codeguru.com.
//
// And as always, please give credit where credit is
// due. Don't remove my name from the source.
///////////////////////////////////////////////////////////////////////////////
// Modified by Hans Dietrich hdietrich2@hotmail.com
///////////////////////////////////////////////////////////////////////////////
#ifndef CCLIPBOARD_H
#define CCLIPBOARD_H
class CClipboard
{
public:
static CString GetText();
static BOOL GetText(LPSTR lpszBuffer, int nBufSize);
static DWORD GetTextLength();
static BOOL SetText(LPCTSTR lpszBuffer);
};
#endif

View File

@@ -0,0 +1,85 @@
================================================================================
MFC 라이브러리 : ChatParser 프로젝트 개요
===============================================================================
응용 프로그램 마법사에서 이 ChatParser 응용 프로그램을
만들었습니다. 이 응용 프로그램은 MFC의 기본 사용법을 보여 줄 뿐만 아니라 응용 프로그램
작성을 위한 기본 구조를 제공합니다.
이 파일에는 ChatParser 응용 프로그램을 구성하는 각 파일에 대한
요약 설명이 포함되어 있습니다.
ChatParser.vcproj
응용 프로그램 마법사를 사용하여 생성된 VC++ 프로젝트의 주 프로젝트 파일입니다.
파일을 생성한 Visual C++ 버전에 대한 정보와 응용 프로그램 마법사를 사용하여 선택한
플랫폼, 구성 및 프로젝트 기능에 대한 정보가 들어 있습니다.
ChatParser.h
응용 프로그램의 기본 헤더 파일입니다. 여기에는 다른 프로젝트 관련
헤더(Resource.h 포함)가 들어 있고 CChatParserApp 응용 프로그램
클래스를 선언합니다.
ChatParser.cpp
응용 프로그램 클래스 CChatParserApp이(가) 들어 있는 기본 응용 프로그램
소스 파일입니다.
ChatParser.rc
프로그램에서 사용하는 모든 Microsoft Windows 리소스의 목록입니다.
여기에는 RES 하위 디렉터리에 저장된 아이콘, 비트맵 및 커서가
포함됩니다. 이 파일은 Microsoft Visual C++에서 직접
편집할 수 있습니다. 프로젝트 리소스는 1042에 있습니다.
res\ChatParser.ico
응용 프로그램의 아이콘으로 사용되는 아이콘 파일입니다. 이 아이콘은
주 리소스 파일인 ChatParser.rc에 의해 포함됩니다.
res\ChatParser.rc2
이 파일에는 Microsoft Visual C++ 이외의 다른 도구에서 편집한 리소스가
들어 있습니다. 리소스 편집기로 편집할 수 없는 모든 리소스는
이 파일에 넣어야 합니다.
/////////////////////////////////////////////////////////////////////////////
응용 프로그램 마법사에서 하나의 대화 상자 클래스가 만들어집니다.
ChatParserDlg.h, ChatParserDlg.cpp ? 대화 상자
이 파일에는 CChatParserDlg 클래스가 들어 있습니다. 이 클래스는
응용 프로그램의 주 대화 상자 동작을 정의합니다. 대화 상자의 템플릿은
Microsoft Visual C++에서 편집할 수 있는 ChatParser.rc에 있습니다.
/////////////////////////////////////////////////////////////////////////////
기타 표준 파일:
StdAfx.h, StdAfx.cpp
이 파일은 미리 컴파일된 헤더 파일(PCH)인 ChatParser.pch와
미리 컴파일된 형식 파일인 StdAfx.obj를 빌드하는 데 사용됩니다.
Resource.h
새 리소스 ID를 정의하는 표준 헤더 파일입니다.
Microsoft Visual C++에서 이 파일을 읽고 업데이트합니다.
ChatParser.manifest
응용 프로그램 매니페스트 파일은 Windows XP에서 특정 버전의 Side-by-Side
어셈블리에 대한 응용 프로그램 종속성을 설명하는 데 사용됩니다. 로더는 이 정보를
사용하여 어셈블리 캐시에서 적절한 어셈블리를 로드하거나 응용 프로그램에서 전용
어셈블리를 로드합니다. 응용 프로그램 매니페스트는 응용 프로그램 실행 파일과 같은
폴더에 설치된 외부 .manifest 파일로 재배포를 위해 포함되거나 리소스의 형태로
실행 파일에 포함될 수 있습니다.
/////////////////////////////////////////////////////////////////////////////
기타 참고:
응용 프로그램 마법사는 "TODO:"를 사용하여 추가하거나 사용자 지정해야 하는
소스 코드 부분을 나타냅니다.
응용 프로그램이 공유 DLL에서 MFC를 사용하는 경우 해당 MFC DLL을
재배포해야 합니다. 그리고 응용 프로그램이 운영 체제의 로캘과
다른 언어를 사용하는 경우 해당 지역화된 리소스인 MFC80XXX.DLL을
재배포해야 합니다. 이 두가지 항목에 대한 자세한 내용은
MSDN 설명서의 Visual C++ 응용 프로그램 재배포 항목을
참조하십시오.
/////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,187 @@
#include "stdafx.h"
#include <winsock2.h>
#include <windows.h>
#include "RegFunctions.h"
#include <fstream>
bool Registry::WriteString(const char *FileName_In, const char *Section_In,
const char *KeyName_In, const char *Value_In)
{
return 0 != WritePrivateProfileString(Section_In, KeyName_In, Value_In, FileName_In);
}
unsigned long Registry::ReadInt(const char *FileName_In, const char *Section_In, const char *KeyName_In)
{
return static_cast<unsigned long>(GetPrivateProfileInt(Section_In, KeyName_In, 0, FileName_In));
}
bool Registry::ReadString(const char *FileName_In, const char *Section_In,
const char *KeyName_In, char *Buffer_Out, int nBufferSize)
{
return 0 != GetPrivateProfileString(Section_In, KeyName_In,
NULL, Buffer_Out, nBufferSize, FileName_In);
}
bool Registry::WriteStruct(const char *FileName_In, const char *Section_In,
const char *KeyName_In, void *Value_In, const int Size_in)
{
return 0 != WritePrivateProfileStruct(Section_In, KeyName_In, Value_In, Size_in, FileName_In);
}
bool Registry::ReadStruct(const char *FileName_In, const char *Section_In,
const char *KeyName_In, void *Value_Out, const int Size_in)
{
return 0 != GetPrivateProfileStruct(Section_In, KeyName_In, Value_Out, Size_in, FileName_In);
}
Registry::CSetupFile::CSetupFile()
{
}
Registry::CSetupFile::CSetupFile(const char* szFileName)
{
Open(szFileName);
}
Registry::CSetupFile::~CSetupFile()
{
}
inline unsigned long sdbmHash(const unsigned char *str)
{
unsigned long hash = 0;
int c;
while (c = *str++) { hash = c + (hash << 6) + (hash << 16) - hash; }
return hash;
}
bool Registry::CSetupFile::Open(const char* szFileName)
{
std::string fileLine;
std::string szSection;
std::string szKey;
std::string szValue;
fileLine.reserve(4096);
szSection.reserve(1024);
szKey.reserve(1024);
szValue.reserve(4096);
std::fstream file(szFileName, std::ios_base::in);
std::string::size_type nPosition = std::string::npos;
std::string::size_type nEndPosition = std::string::npos;
std::string::size_type nDataPosition = std::string::npos;
std::string::size_type nDataEndPosition = std::string::npos;
unsigned long dwSectionValue = 0;
if(file.is_open())
{
while(std::getline(file, fileLine))
{
nPosition = fileLine.find_first_not_of(" \r\n\t");
if(std::string::npos != nPosition)
{
if('[' == fileLine[nPosition])
{
// 섹션명임
nEndPosition = fileLine.find_first_of(']', nPosition);
if(std::string::npos != nEndPosition)
{
szSection.assign(fileLine.begin() + nPosition + 1,
fileLine.begin() + nEndPosition);
dwSectionValue = sdbmHash(reinterpret_cast<const unsigned char*>(szSection.c_str()));
}
}
else if(0 != fileLine.compare(nPosition, sizeof(char) * 2, "//"))
{
// 주석 아님
nEndPosition = fileLine.find_first_of('=', nPosition);
if(std::string::npos != nEndPosition)
{
// nEndPosition 좌우로 Key - Value Pair임.
nDataEndPosition = fileLine.find_last_not_of("= \t", nEndPosition);
if(std::string::npos != nDataEndPosition)
{
// 키 읽어옴.
szKey.assign(fileLine.begin() + nPosition,
fileLine.begin() + nDataEndPosition + 1);
nDataPosition = fileLine.find_first_not_of("= \t", nEndPosition);
if(std::string::npos != nDataPosition)
{
nDataEndPosition = fileLine.find_last_not_of(" \r\n\t");
if(std::string::npos != nDataEndPosition)
{
// 값 읽어옴
m_SetupMap.insert(SetupMap::value_type(
sdbmHash(reinterpret_cast<const unsigned char*>(szKey.c_str())) + dwSectionValue,
Data(szSection, szKey,
std::string(fileLine.begin() + nDataPosition, fileLine.begin() + nDataEndPosition + 1))));
}
}
}
}
}
}
}
}
return false;
}
void Registry::CSetupFile::Clear()
{
m_SetupMap.clear();
}
const char* Registry::CSetupFile::GetString(const char* szSection, const char* szKey,
const char* szDefaultValue)
{
DWORD dwHashValue = sdbmHash(reinterpret_cast<const unsigned char*>(szSection))
+ sdbmHash(reinterpret_cast<const unsigned char*>(szKey));
std::pair<SetupMap::iterator, SetupMap::iterator> pos_pair = m_SetupMap.equal_range(dwHashValue);
for(; pos_pair.first != pos_pair.second; ++pos_pair.first)
{
Data& data = pos_pair.first->second;
if(0 == data.m_szSection.compare(szSection) &&
0 == data.m_szKey.compare(szKey))
{
return data.m_szValue.c_str();
}
}
return szDefaultValue;
}
unsigned int Registry::CSetupFile::GetInt(const char* szSection, const char* szKey,
unsigned int nDefaultValue)
{
const char* szStr = GetString(szSection, szKey);
if(0 != szStr)
{
return atoi(szStr);
}
return nDefaultValue;
}

View File

@@ -0,0 +1,59 @@
#ifndef _REGISTRY_FUNCTIONS_H_
#define _REGISTRY_FUNCTIONS_H_
#include <map>
#include <string>
namespace Registry
{
bool WriteString(const char *FileName_In, const char *Section_In,
const char *KeyName_In, const char *Value_In);
unsigned long ReadInt(const char *FileName_In,
const char *Section_In, const char *KeyName_In);
bool ReadString(const char *FileName_In, const char *Section_In,
const char *KeyName_In, char *Buffer_Out, int nBufferSize);
bool WriteStruct(const char *FileName_In, const char *Section_In,
const char *KeyName_In, void *Value_In, const int Size_in);
bool ReadStruct(const char *FileName_In, const char *Section_In,
const char *KeyName_In, void *Value_Out, const int Size_in);
class CSetupFile
{
public:
CSetupFile();
CSetupFile(const char* szFileName);
~CSetupFile();
bool Open(const char* szFileName);
void Clear();
const char* GetString(const char* szSection, const char* szKey, const char* szDefaultValue = 0);
unsigned int GetInt(const char* szSection, const char* szKey, unsigned int nDefaultValue = 0);
private:
struct Data
{
std::string m_szSection;
std::string m_szKey;
std::string m_szValue;
Data(const std::string& szSection, const std::string& szKey, const std::string& szValue)
: m_szSection(szSection), m_szKey(szKey), m_szValue(szValue)
{
}
};
typedef std::multimap<unsigned long, Data> SetupMap;
SetupMap m_SetupMap;
};
};
#endif

View File

@@ -0,0 +1,702 @@
// XListBox.cpp
//
// Author: Hans Dietrich
// hdietrich2@hotmail.com
//
// This software is released into the public domain.
// You are free to use it in any way you like.
//
// This software is provided "as is" with no expressed
// or implied warranty. I accept no liability for any
// damage or loss of business that this software may cause.
//
// Notes on use: To use in an MFC project, first create
// a listbox using the standard dialog editor.
// Be sure to mark the listbox as OWNERDRAW
// FIXED, and check the HAS STRINGS box.
// Using Class Wizard, create a variable for
// the listbox. Finally, manually edit the
// dialog's .h file and replace CListBox with
// CXListBox, and #include XListBox.h.
//
///////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "XListBox.h"
#include "Clipboard.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
// NOTE - following table must be kept in sync with ColorPickerCB.cpp
static COLORREF ColorTable[16] = { RGB( 0, 0, 0), // Black
RGB(255, 255, 255), // White
RGB(255, 255, 255), // ChatNormal
RGB(141, 180, 244), // ChatParty
RGB(255, 255, 255), // ChatFriend
RGB(255, 229, 57), // ChatGuild
RGB(255, 255, 255), // ChatStall
RGB( 53, 218, 193), // ChatShout
RGB(220, 220, 220), // ChatAdminNormal
RGB(255, 128, 64), // ChatAdminShout
RGB(255, 128, 239), // ChatWhisper
RGB(255, 0, 255), // ChatNotice
RGB(204, 128, 255), // ChatTrade
RGB( 38, 255, 38), // Call : 운영자를 부르는 유저의 목소리-_ -a
RGB(255, 0, 255), // GMReport
RGB( 0, 0, 0) }; // BackColor
BEGIN_MESSAGE_MAP(CXListBox, CListBox)
//{{AFX_MSG_MAP(CXListBox)
ON_WM_LBUTTONDBLCLK()
ON_WM_CONTEXTMENU()
ON_COMMAND(ID_EDIT_SELECT_ALL, OnEditSelectAll)
ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
ON_COMMAND(ID_EDIT_CLEAR, OnEditClear)
ON_WM_ERASEBKGND()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#define new DEBUG_NEW
/////////////////////////////////////////////////////////////////////////////
// CXListBox
CXListBox::CXListBox()
{
m_ColorWindow = ::GetSysColor(COLOR_WINDOW);
m_ColorHighlight = ::GetSysColor(COLOR_HIGHLIGHT);
m_ColorWindowText = ::GetSysColor(COLOR_WINDOWTEXT);
m_ColorHighlightText = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
m_bColor = TRUE;
m_cxExtent = 0;
m_nTabPosition = 8; // tab stops every 8 columns
m_nSpaceWidth = 7;
m_nContextMenuId = (UINT)-1;
for (int i = 0; i < MAXTABSTOPS; i++)
m_nTabStopPositions[i] = (i+1) * m_nTabPosition * m_nSpaceWidth;
}
CXListBox::~CXListBox()
{
}
//////////////////////////////////////////////////////////////////////////////
// MeasureItem
void CXListBox::MeasureItem(LPMEASUREITEMSTRUCT)
{
}
//////////////////////////////////////////////////////////////////////////////
// CompareItem
int CXListBox::CompareItem(LPCOMPAREITEMSTRUCT)
{
return 0;
}
//////////////////////////////////////////////////////////////////////////////
// DrawItem
void CXListBox::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
CDC* pDC = CDC::FromHandle(lpDIS->hDC);
COLORREF oldtextcolor, oldbackgroundcolor;
pDC->GetCharWidth((UINT) ' ', (UINT) ' ', &m_nSpaceWidth);
pDC->GetCharWidth((UINT) 'c', (UINT) 'c', &m_nAveCharWidth);
for (int i = 0; i < MAXTABSTOPS; i++)
m_nTabStopPositions[i] = (i+1) * m_nAveCharWidth * m_nTabPosition;
// draw focus rectangle when no items in listbox
if (lpDIS->itemID == (UINT)-1)
{
if (lpDIS->itemAction & ODA_FOCUS)
pDC->DrawFocusRect(&lpDIS->rcItem);
return;
}
else
{
int selChange = lpDIS->itemAction & ODA_SELECT;
int focusChange = lpDIS->itemAction & ODA_FOCUS;
int drawEntire = lpDIS->itemAction & ODA_DRAWENTIRE;
if (selChange || drawEntire)
{
BOOL sel = lpDIS->itemState & ODS_SELECTED;
int nLen = CListBox::GetTextLen(lpDIS->itemID);
if (nLen != LB_ERR)
{
char *buf = new char [nLen + 10];
ASSERT(buf);
if (buf && (GetTextWithColor(lpDIS->itemID, (LPSTR)buf) != LB_ERR))
{
// set text color from first character in string -
// NOTE: 1 was added to color index to avoid asserts by CString
int itext = int (buf[0] - 1);
// set background color from second character in string -
// NOTE: 1 was added to color index to avoid asserts by CString
int iback = int (buf[1] - 1);
buf[0] = ' ';
buf[1] = ' ';
COLORREF textcolor = sel ? m_ColorHighlightText : ColorTable[itext];
oldtextcolor = pDC->SetTextColor(textcolor);
COLORREF backgroundcolor = sel ? m_ColorHighlight : ColorTable[iback];
oldbackgroundcolor = pDC->SetBkColor(backgroundcolor);
// fill the rectangle with the background color the fast way
pDC->ExtTextOut(0, 0, ETO_OPAQUE, &lpDIS->rcItem, NULL, 0, NULL);
pDC->TabbedTextOut(lpDIS->rcItem.left, lpDIS->rcItem.top, &buf[2],
(int)strlen(&buf[2]), MAXTABSTOPS, (LPINT)m_nTabStopPositions, 0);
CSize size;
size = pDC->GetOutputTextExtent(&buf[2]);
int nScrollBarWidth = ::GetSystemMetrics(SM_CXVSCROLL);
size.cx += nScrollBarWidth; // in case of vertical scrollbar
int cxExtent = (size.cx > m_cxExtent) ? size.cx : m_cxExtent;
if (cxExtent > m_cxExtent)
{
m_cxExtent = cxExtent;
SetHorizontalExtent(m_cxExtent+(m_cxExtent/32));
}
}
if (buf)
delete [] buf;
}
}
if (focusChange || (drawEntire && (lpDIS->itemState & ODS_FOCUS)))
{
pDC->DrawFocusRect(&lpDIS->rcItem);
}
}
}
//////////////////////////////////////////////////////////////////////////////
// GetTextWithColor - get text string with color bytes
int CXListBox::GetTextWithColor(int nIndex, LPTSTR lpszBuffer) const
{
if (!::IsWindow(m_hWnd))
{
ASSERT(FALSE);
return LB_ERR;
}
ASSERT(lpszBuffer);
lpszBuffer[0] = 0;
return CListBox::GetText(nIndex, lpszBuffer);
}
//////////////////////////////////////////////////////////////////////////////
// GetTextWithColor - get text string with color bytes
void CXListBox::GetTextWithColor(int nIndex, CString& rString) const
{
if (!::IsWindow(m_hWnd))
{
ASSERT(FALSE);
return;
}
rString.Empty();
CListBox::GetText(nIndex, rString);
}
//////////////////////////////////////////////////////////////////////////////
// GetText - for compatibility with CListBox (no color bytes)
int CXListBox::GetText(int nIndex, LPTSTR lpszBuffer) const
{
if (!::IsWindow(m_hWnd))
{
ASSERT(FALSE);
return LB_ERR;
}
ASSERT(lpszBuffer);
lpszBuffer[0] = 0;
int nRet = CListBox::GetText(nIndex, lpszBuffer);
int n = (int)strlen(lpszBuffer);
if (n > 2)
memcpy(&lpszBuffer[0], &lpszBuffer[2], n-1); // copy nul too
return nRet;
}
//////////////////////////////////////////////////////////////////////////////
// GetText - for compatibility with CListBox (no color bytes)
void CXListBox::GetText(int nIndex, CString& rString) const
{
if (!::IsWindow(m_hWnd))
{
ASSERT(FALSE);
return;
}
CString str;
str.Empty();
CListBox::GetText(nIndex, str);
if ((!str.IsEmpty()) && (str.GetLength() > 2))
rString = str.Mid(2);
else
rString.Empty();
}
//////////////////////////////////////////////////////////////////////////////
// GetTextLen - for compatibility with CListBox (no color bytes)
int CXListBox::GetTextLen(int nIndex) const
{
if (!::IsWindow(m_hWnd))
{
ASSERT(FALSE);
return LB_ERR;
}
int n = CListBox::GetTextLen(nIndex);
if (n != LB_ERR && n >= 2)
n -= 2;
return n;
}
//////////////////////////////////////////////////////////////////////////////
// SearchString
int CXListBox::SearchString(int nStartAfter, LPCTSTR lpszItem, BOOL bExact) const
{
if (!::IsWindow(m_hWnd))
{
ASSERT(FALSE);
return LB_ERR;
}
// start the search after specified index
int nIndex = nStartAfter + 1;
int nCount = GetCount();
if (nCount == LB_ERR)
return LB_ERR;
// convert string to search for to lower case
CString strItem;
strItem = lpszItem;
strItem.MakeLower();
int nItemSize = strItem.GetLength();
CString strText;
// search until end
for ( ; nIndex < nCount; nIndex++)
{
GetText(nIndex, strText);
strText.MakeLower();
if (!bExact)
strText = strText.Left(nItemSize);
if (strText == strItem)
return nIndex;
}
// if we started at beginning there is no more to do, search failed
if (nStartAfter == -1)
return LB_ERR;
// search until we reach beginning index
for (nIndex = 0; (nIndex <= nStartAfter) && (nIndex < nCount); nIndex++)
{
GetText(nIndex, strText);
strText.MakeLower();
if (!bExact)
strText = strText.Left(nItemSize);
if (strText == strItem)
return nIndex;
}
return LB_ERR;
}
//////////////////////////////////////////////////////////////////////////////
// FindString
int CXListBox::FindString(int nStartAfter, LPCTSTR lpszItem) const
{
return SearchString(nStartAfter, lpszItem, FALSE);
}
//////////////////////////////////////////////////////////////////////////////
// SelectString
int CXListBox::SelectString(int nStartAfter, LPCTSTR lpszItem)
{
int rc = SearchString(nStartAfter, lpszItem, FALSE);
if (rc != LB_ERR)
SetCurSel(rc);
return rc;
}
//////////////////////////////////////////////////////////////////////////////
// FindStringExact
int CXListBox::FindStringExact(int nStartAfter, LPCTSTR lpszItem) const
{
return SearchString(nStartAfter, lpszItem, TRUE);
}
//////////////////////////////////////////////////////////////////////////////
// InsertString - override to add text color
int CXListBox::InsertString(int nIndex, LPCTSTR lpszItem)
{
if (!::IsWindow(m_hWnd))
{
ASSERT(FALSE);
return LB_ERR;
}
CString s;
s.Empty();
s = lpszItem;
Color tc = Black; // to force black-only text
Color bc = White;
UINT nColor = (UINT) tc;
ASSERT(nColor < 16);
if (nColor >= 16)
tc = Black;
// don't display \r or \n characters
int i;
while ((i = s.FindOneOf("\r\n")) != -1)
s.SetAt(i, ' ');
// first character in string is color -- add 1 to color
// to avoid asserts by CString class
CString t;
t .Empty();
t += (char) (tc + 1);
t += (char) (bc + 1);
t += s;
// try to insert the string into the listbox
i = CListBox::InsertString(nIndex, t);
return i;
}
//////////////////////////////////////////////////////////////////////////////
// AddString - override to add text color
void CXListBox::AddString(LPCTSTR lpszItem)
{
AddLine(CXListBox::Black, CXListBox::White, lpszItem, true);
}
//////////////////////////////////////////////////////////////////////////////
// AddLine
void CXListBox::AddLine(Color tc, Color bc, LPCTSTR lpszLine, BOOL bAutoScroll)
{
if (!::IsWindow(m_hWnd))
{
ASSERT(FALSE);
return;
}
CString s;
s.Empty();
s = lpszLine;
if (!m_bColor)
{
tc = Black; // to force black-only text
bc = White;
}
UINT nColor = (UINT) tc;
ASSERT(nColor < 16);
if (nColor >= 16)
tc = Black;
// don't display \r or \n characters
int i;
while ((i = s.FindOneOf("\r\n")) != -1)
s.SetAt(i, ' ');
// first character in string is color -- add 1 to color
// to avoid asserts by CString class
CString t;
t.Empty();
t += (char) (tc + 1);
t += (char) (bc + 1);
t += s;
// try to add the string to the listbox
i = CListBox::AddString(t);
if (i == LB_ERRSPACE)
{
// will get LB_ERRSPACE if listbox is out of memory
int n = GetCount();
if (n == LB_ERR)
return;
if (n < 2)
return;
// try to delete some strings to free up some room --
// don't spend too much time deleting strings, since
// we might be getting a burst of messages
n = (n < 20) ? (n - 1) : 20;
if (n <= 0)
n = 1;
SetRedraw(FALSE);
for (i = 0; i < n; i++)
DeleteString(0);
i = CListBox::AddString(t);
SetRedraw(TRUE);
}
if(bAutoScroll && (i >= 0))
{
SetTopIndex(i);
}
SetCurSel(-1);
}
///////////////////////////////////////////////////////////////////////////////
// Printf
void _cdecl CXListBox::Printf(Color tc, Color bc, UINT nID, LPCTSTR lpszFmt, ...)
{
char buf[1024], fmt[1024];
va_list marker;
// load format string from string resource if
// a resource ID was specified
if (nID)
{
CString s;
if (!s.LoadString(nID))
{
sprintf(s.GetBufferSetLength(80), "Failed to load string resource %u",
nID);
s.ReleaseBuffer(-1);
}
strncpy(fmt, s, sizeof(fmt)-1);
}
else
{
// format string was passed as parameter
strncpy(fmt, lpszFmt, sizeof(fmt)-1);
}
fmt[sizeof(fmt)-1] = 0;
// combine output string and variables
va_start(marker, lpszFmt);
_vsnprintf(buf, sizeof(buf)-1, fmt, marker);
va_end(marker);
buf[sizeof(buf)-1] = 0;
AddLine(tc, bc, buf, true);
}
//////////////////////////////////////////////////////////////////////////////
// EnableColor
void CXListBox::EnableColor (BOOL bEnable)
{
m_bColor = bEnable;
}
//////////////////////////////////////////////////////////////////////////////
// SetTabPosition
void CXListBox::SetTabPosition(int nSpacesPerTab)
{
ASSERT(nSpacesPerTab > 0 && nSpacesPerTab < 11);
m_nTabPosition = nSpacesPerTab;
CDC* pDC = GetDC();
if (pDC)
{
TEXTMETRIC tm;
pDC->GetTextMetrics(&tm);
pDC->GetCharWidth((UINT) ' ', (UINT) ' ', &m_nSpaceWidth);
pDC->GetCharWidth((UINT) '9', (UINT) '9', &m_nAveCharWidth);
for (int i = 0; i < MAXTABSTOPS; i++)
m_nTabStopPositions[i] = (i+1) * m_nAveCharWidth * m_nTabPosition;
ReleaseDC(pDC);
}
}
//////////////////////////////////////////////////////////////////////////////
// GetVisibleLines
int CXListBox::GetVisibleLines()
{
int nCount = 0;
CDC* pDC = GetDC();
if (pDC)
{
TEXTMETRIC tm;
pDC->GetTextMetrics(&tm);
int h = tm.tmHeight + tm.tmInternalLeading;
ReleaseDC(pDC);
CRect rect;
GetClientRect(&rect);
nCount = rect.Height() / h;
}
return nCount;
}
//////////////////////////////////////////////////////////////////////////////
// ResetContent
void CXListBox::ResetContent()
{
if (!::IsWindow(m_hWnd))
{
ASSERT(FALSE);
return;
}
CListBox::ResetContent();
m_cxExtent = 0;
SetHorizontalExtent(m_cxExtent);
}
//////////////////////////////////////////////////////////////////////////////
// SetFont
void CXListBox::SetFont(CFont *pFont, BOOL bRedraw)
{
if (!::IsWindow(m_hWnd))
{
ASSERT(FALSE);
return;
}
CListBox::SetFont(pFont, bRedraw);
CDC* pDC = GetDC();
if (pDC)
{
CFont *pOldFont = pDC->SelectObject(pFont);
TEXTMETRIC tm;
pDC->GetTextMetrics(&tm);
int h = tm.tmHeight;
SetItemHeight(0, h);
pDC->SelectObject(pOldFont);
pDC->GetCharWidth((UINT) ' ', (UINT) ' ', &m_nSpaceWidth);
pDC->GetCharWidth((UINT) '9', (UINT) '9', &m_nAveCharWidth);
for (int i = 0; i < MAXTABSTOPS; i++)
m_nTabStopPositions[i] = (i+1) * m_nAveCharWidth * m_nTabPosition;
ReleaseDC(pDC);
}
m_cxExtent = 0;
}
//////////////////////////////////////////////////////////////////////////////
// OnLButtonDblClk
void CXListBox::OnLButtonDblClk(UINT nFlags, CPoint point)
{
CListBox::OnLButtonDblClk(nFlags, point);
}
//////////////////////////////////////////////////////////////////////////////
// OnContextMenu
void CXListBox::OnContextMenu(CWnd* /*pWnd*/, CPoint point)
{
if (m_nContextMenuId == -1)
{
TRACE(" no context menu\n");
return;
}
CMenu menu;
if (!menu.LoadMenu(m_nContextMenuId))
{
TRACE(" ERROR failed to load %d\n", m_nContextMenuId);
return;
}
menu.GetSubMenu(0)->TrackPopupMenu(0,
point.x, point.y, this, NULL);
}
//////////////////////////////////////////////////////////////////////////////
// OnEditCopy
void CXListBox::OnEditCopy()
{
CString str;
str.Empty();
int nCount = GetCount();
int nSel = 0;
for (int i = 0; i < nCount; i++)
{
if (GetSel(i) > 0)
{
CString s;
s.Empty();
GetText(i, s);
if (!s.IsEmpty())
{
nSel++;
s.TrimLeft("\r\n");
s.TrimRight("\r\n");
if (s.Find('\n') == -1)
s += "\n";
s.Replace("\t", " ");
str += s;
}
}
}
if (!str.IsEmpty())
CClipboard::SetText(str);
}
//////////////////////////////////////////////////////////////////////////////
// OnEditClear
void CXListBox::OnEditClear()
{
ResetContent();
}
//////////////////////////////////////////////////////////////////////////////
// OnEditSelectAll
void CXListBox::OnEditSelectAll()
{
if (!::IsWindow(m_hWnd))
{
ASSERT(FALSE);
return;
}
SelItemRange(TRUE, 0, GetCount()-1);
}
// Add by zun!
BOOL CXListBox::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}

View File

@@ -0,0 +1,93 @@
// XListBox.h
//
// Author: Hans Dietrich
// hdietrich2@hotmail.com
//
// This software is released into the public domain.
// You are free to use it in any way you like.
//
// This software is provided "as is" with no expressed
// or implied warranty. I accept no liability for any
// damage or loss of business that this software may cause.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef XLISTBOX_H
#define XLISTBOX_H
///////////////////////////////////////////////////////////////////////////////
// CXListBox class
class CXListBox : public CListBox
{
// Constructors
public:
CXListBox();
~CXListBox();
// Attributes
public:
int m_cxExtent;
int m_nTabPosition;
BOOL m_bColor;
COLORREF m_ColorWindow;
COLORREF m_ColorHighlight;
COLORREF m_ColorWindowText;
COLORREF m_ColorHighlightText;
// NOTE - following list must be kept in sync with ColorPickerCB.cpp
enum Color{ Black, White,
ChatNormal, ChatParty, ChatFriend, ChatGuild, ChatStall, ChatShout,
ChatAdminNormal, ChatAdminShout, ChatWhisper, ChatNotice, ChatTrade, Call, GMReport, BackColor
};
void EnableColor(BOOL bEnable);
// Operations
public:
void AddLine(Color tc, Color bc, LPCTSTR lpszLine, BOOL bAutoScroll = TRUE);
void AddString(LPCTSTR lpszItem);
int FindString(int nStartAfter, LPCTSTR lpszItem) const;
int FindStringExact(int nStartAfter, LPCTSTR lpszItem) const;
int GetText(int nIndex, LPTSTR lpszBuffer) const;
void GetText(int nIndex, CString& rString) const;
int GetTextLen(int nIndex) const;
int GetTextWithColor(int nIndex, LPTSTR lpszBuffer) const;
void GetTextWithColor(int nIndex, CString& rString) const;
int GetVisibleLines();
int InsertString(int nIndex, LPCTSTR lpszItem);
void _cdecl Printf(Color tc, Color bc, UINT nID, LPCTSTR lpszFmt, ...);
virtual void ResetContent();
int SelectString(int nStartAfter, LPCTSTR lpszItem);
void SetContextMenuId(UINT nId) { m_nContextMenuId = nId; }
virtual void SetFont(CFont *pFont, BOOL bRedraw = TRUE);
void SetTabPosition(int nSpacesPerTab);
// Implementation
protected:
int SearchString(int nStartAfter, LPCTSTR lpszItem, BOOL bExact) const;
#define MAXTABSTOPS 100
int m_nTabStopPositions[MAXTABSTOPS];
int m_nSpaceWidth;
int m_nAveCharWidth;
UINT m_nContextMenuId;
virtual int CompareItem (LPCOMPAREITEMSTRUCT lpCIS);
virtual void DrawItem (LPDRAWITEMSTRUCT lpDIS);
virtual void MeasureItem (LPMEASUREITEMSTRUCT lpMIS);
// Generated message map functions
//{{AFX_MSG(CXListBox)
afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
afx_msg void OnEditCopy();
afx_msg void OnEditClear();
afx_msg void OnEditSelectAll();
afx_msg BOOL OnEraseBkgnd(CDC* pDC); // Add by zun!
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
#endif
///////////////////////////////////////////////////////////////////////////////

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -0,0 +1,13 @@
//
// ChatParser.RC2 - Microsoft Visual C++에서 직접 편집하지 않는 리소스
//
#ifdef APSTUDIO_INVOKED
#error 이 파일은 Microsoft Visual C++에서 편집할 수 없습니다.
#endif //APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
// 여기에 수동으로 편집한 리소스를 추가합니다.
/////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,31 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by ChatParser.rc
//
#define IDM_ABOUTBOX 0x0010
#define IDD_ABOUTBOX 100
#define IDS_ABOUTBOX 101
#define IDD_CHATPARSER_DIALOG 102
#define IDR_MAINFRAME 128
#define IDC_OPEN_FILENAME 1000
#define IDC_OPENFILE 1001
#define IDC_FINDLIST 1002
#define IDC_CHATLIST 1003
#define IDC_OLDVERSION 1004
#define IDC_SERVERID 1005
#define IDC_ZONEID 1006
#define IDC_ZONEID2 1007
#define IDC_CHATTYPE 1007
#define IDC_FINDNAME 1008
#define IDC_FINDNAMECHK 1009
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 129
#define _APS_NEXT_COMMAND_VALUE 32771
#define _APS_NEXT_CONTROL_VALUE 1009
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@@ -0,0 +1,76 @@
// stdafx.cpp : 표준 포함 파일만 들어 있는 소스 파일입니다.
// ChatParser.pch는 미리 컴파일된 헤더가 됩니다.
// stdafx.obj에는 미리 컴파일된 형식 정보가 포함됩니다.
#include "stdafx.h"
#include "ChatParserSetup.h"
/// \brief 섹션명과 키로 ini 셋업 파일에서 셋팅된 값 얻기
/// \param szSection 얻고자하는 값이 속한 섹션명
/// \param szKey 얻고자 하는 값에 매칭되는 키
const char* GetMyINIString(const char* szSection, const char* szKey)
{
const char* szResult = CChatParserSetup::GetInstance().GetString(szSection, szKey, 0);
if(0 == szResult)
{
CString strErr;
strErr.Format("Setup string load failed! - key: %s", szKey);
AfxMessageBox(strErr, MB_ICONSTOP);
return "???";
}
return szResult;
}
const int GetChatType(const char* szType)
{
int iCount = 17;
char* strFind[] = {
"NORMAL",
"PARTY",
"FRIEND",
"GUILD",
"CLIENT_LOG",
"STALL",
"SHOUT",
"ADMIN_NORMAL_CHAT",
"ADMIN_SHOUT",
"WHISPER",
"TRADE",
"CAMP_SHOP",
"NOTIFY_CHAR_INFO",
"FIND_PARTY",
"ENEMY_CHECK",
"DICE",
"NOTICE"
};
int FindID[] = {
NORMAL,
PARTY,
FRIEND,
GUILD,
CLIENT_LOG,
STALL,
SHOUT,
ADMIN_NORMAL_CHAT,
ADMIN_SHOUT,
WHISPER,
TRADE,
CAMP_SHOP,
NOTIFY_CHAR_INFO,
FIND_PARTY,
ENEMY_CHECK,
DICE,
NOTICE
};
for(int i = 0; i < iCount; ++i)
{
if(strcmp(szType, strFind[i]) == 0)
return FindID[i]+1;
}
return 0;
}

View File

@@ -0,0 +1,111 @@
// stdafx.h : 자주 사용하지만 자주 변경되지는 않는
// 표준 시스템 포함 파일 및 프로젝트 관련 포함 파일이
// 들어 있는 포함 파일입니다.
#pragma once
#ifndef _SECURE_ATL
#define _SECURE_ATL 1
#endif
#ifndef VC_EXTRALEAN
#define VC_EXTRALEAN // 거의 사용되지 않는 내용은 Windows 헤더에서 제외합니다.
#endif
// 아래 지정된 플랫폼에 우선하는 플랫폼을 대상으로 하는 경우 다음 정의를 수정하십시오.
// 다른 플랫폼에 사용되는 해당 값의 최신 정보는 MSDN을 참조하십시오.
#ifndef WINVER // Windows XP 이상에서만 기능을 사용할 수 있습니다.
#define WINVER 0x0501 // 다른 버전의 Windows에 맞도록 적합한 값으로 변경해 주십시오.
#endif
#ifndef _WIN32_WINNT // Windows XP 이상에서만 기능을 사용할 수 있습니다.
#define _WIN32_WINNT 0x0501 // 다른 버전의 Windows에 맞도록 적합한 값으로 변경해 주십시오.
#endif
#ifndef _WIN32_WINDOWS // Windows 98 이상에서만 기능을 사용할 수 있습니다.
#define _WIN32_WINDOWS 0x0410 // Windows Me 이상에 맞도록 적합한 값으로 변경해 주십시오.
#endif
#ifndef _WIN32_IE // IE 6.0 이상에서만 기능을 사용할 수 있습니다.
#define _WIN32_IE 0x0600 // 다른 버전의 IE에 맞도록 적합한 값으로 변경해 주십시오.
#endif
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // 일부 CString 생성자는 명시적으로 선언됩니다.
// MFC의 공통 부분과 무시 가능한 경고 메시지에 대한 숨기기를 해제합니다.
#define _AFX_ALL_WARNINGS
#include <afxwin.h> // MFC 핵심 및 표준 구성 요소입니다.
#include <afxext.h> // MFC 확장입니다.
#ifndef _AFX_NO_OLE_SUPPORT
#include <afxdtctl.h> // Internet Explorer 4 공용 컨트롤에 대한 MFC 지원입니다.
#endif
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h> // Windows 공용 컨트롤에 대한 MFC 지원입니다.
#endif // _AFX_NO_AFXCMN_SUPPORT
#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
#pragma warning(disable : 4996) // vs2005에서 추가됨. 보안상의 이유로 더 이상 사용되지 않는 MFC나 ATL 함수를 사용하는 경우에도 C4996이 발생할 수 있습니다
enum ChatCmdType
{
NORMAL = 0, // 현재 캐릭터 좌표를 가지고 판단.
PARTY = 1, // 파티 채팅
FRIEND = 2, // 친구 채팅 (이름 char[16] * m_cNum - MAX 100개)
GUILD = 3, // 길드 채팅
CLIENT_LOG = 5,
STALL = 6, // 노점상 채팅 (이름 char[16] * m_cNum - MAX 10개)
SHOUT = 7, // 외치기
ADMIN_NORMAL_CHAT = 8, // 운영자 통상 채팅 (Ack로만 사용)
ADMIN_SHOUT = 9, // 운영자 외치기 (Ack로만 사용)
WHISPER = 10, // 이 번호는 쓰이지 않는다.Whisper는 별도의 패킷을 사용하기 때문이다. 단, 로그시에 쓰인다.
TRADE = 11, // 외치기와 동일 (색 구분용으로 다른 커맨드로 만듬)
CAMP_SHOP = 12, // 길드 요새 상점 채팅 (이름 char[16] * m_cNum - MAX 10개)
NOTIFY_CHAR_INFO = 13, // 운영자 명령 hp
FIND_PARTY = 14, // 파티 찾기
ENEMY_CHECK = 15, // 적아군 식별.
DICE = 16, // 주사위 채팅 (파티채팅과 동일)
GMREPORT = 17, // 지엠 채팅
NOTICE = 255,
PktChatMaxSize = 180
};
const char* GetMyINIString(const char* szSection, const char* szKey);
const int GetChatType(const char* szType);

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="ks_c_5601-1987"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="Executable"
ProjectGUID="{A4363ECD-EA34-4C86-A0B2-B2BB09F45AFC}"
Keyword="MakeFileProj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="10">
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="10">
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Release"
Filter="">
<File
RelativePath=".\release\RylMonitoringToolSetup.ini">
</File>
<File
RelativePath=".\release\RylSetupManageTool.ini">
</File>
<File
RelativePath=".\release\RylSetupServerGroup.ini">
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

Binary file not shown.

View File

@@ -0,0 +1,3 @@
[ManageClient]
ManageServerIP=67.228.215.235
ManageServerPort=12538

View File

@@ -0,0 +1,138 @@
// 최종수정일: 2005-05-19
[MANAGER_SERVER_CONNECTION]
MANAGER_SERVER_IP = 122.49.75.3
[CHAT_SERVER_CONNECTION]
CHAT_SERVER_NUM = 2
CHAT_SERVER_IP_00 = 0
CHAT_SERVER_INDEX_00 = 0
CHAT_SERVER_IP_01 = 122.49.75.3
CHAT_SERVER_INDEX_01 = 1
//CHAT_SERVER_IP_02 = 67.18.189.3
//CHAT_SERVER_INDEX_02 = 2
[SERVER_GROUP_INFO]
SERVER_GROUP_NUM = 2
SERVER_GROUP_NAME_00 = TEST
SERVER_GROUP_INDEX_00 = 0
SERVER_GROUP_NAME_01 = Ichman
SERVER_GROUP_INDEX_01 = 1
SERVER_GROUP_NAME_02 = IVERIA
SERVER_GROUP_INDEX_02 = 2
[ZONE_INFO]
ZONE_NUM = 9
ZONE_INDEX_00 = 1
ZONE_NAME_00 = Zone1
ZONE_INDEX_01 = 2
ZONE_NAME_01 = Zone2
ZONE_INDEX_02 = 4
ZONE_NAME_02 = Zone4
ZONE_INDEX_03 = 5
ZONE_NAME_03 = Zone5
ZONE_INDEX_04 = 8
ZONE_NAME_04 = Zone8
ZONE_INDEX_05 = 12
ZONE_NAME_05 = Zone12
ZONE_INDEX_06 = 16
ZONE_NAME_06 = Zone16
ZONE_INDEX_07 = 17
ZONE_NAME_07 = Zone17
ZONE_INDEX_08 = 18
ZONE_NAME_08 = Zone18
[CHAT_TYPE_INFO]
CHAT_TYPE_NUM = 11
CHAT_TYPE_NAME_00 = NORMAL
CHAT_TYPE_NAME_01 = PARTY
CHAT_TYPE_NAME_02 = FRIEND
CHAT_TYPE_NAME_03 = GUILD
CHAT_TYPE_NAME_04 = STALL
CHAT_TYPE_NAME_05 = SHOUT
CHAT_TYPE_NAME_06 = ADMIN_NORMAL
CHAT_TYPE_NAME_07 = ADMIN_SHOUT
CHAT_TYPE_NAME_08 = WHISPER
CHAT_TYPE_NAME_09 = NOTICE
CHAT_TYPE_NAME_10 = TRADE
SEND_CHAT_TYPE_NUM = 2
SEND_CHAT_TYPE_NAME_00 = SHOUT
SEND_CHAT_TYPE_NAME_01 = ADMIN_SHOUT
[CHANNEL_INFO]
CHANNEL_NUM = 1
[LOCAL_STRING]
STRING_001 = 현재라인
STRING_002 = 라인수 (최대 5000라인)
STRING_003 = 자동스크롤
STRING_004 = 채팅로그출력
STRING_005 = 모니터링창 비우기
STRING_006 = [필터 옵션]
STRING_007 = 서버 그룹
STRING_008 = 채팅 타입
STRING_009 = [유저 동접 정보]
STRING_010 = 관리서버 연결 상태:
STRING_011 = 동접로그 출력
STRING_012 = 총합:
STRING_013 = 관리서버 인증
STRING_014 = GM명
STRING_015 = 대상 캐릭터 명
STRING_016 = 메세지:
STRING_017 = 보내기
STRING_018 = 작업 결과:
STRING_019 = 채팅 서버 인증
STRING_020 = [창 전환]>>>>
STRING_021 = 대화 상대:
STRING_022 = 대상 계정 또는 UID
STRING_023 = 계정으로 귓말 보내기
STRING_024 = 귓속말 할 대상은 한명만 지정할 수 있습니다.
STRING_025 = 전송 조건이 잘못되었습니다.
STRING_026 = 메세지를 전송하는데 실패했습니다.
STRING_027 = 연결됨
STRING_028 = 연결 끊김
STRING_029 = 1대1 대화를 사용할 수 없는 로우입니다.
STRING_030 = 채팅 서버 연결 끊김 : 세션을 얻는데 실패했습니다.
STRING_031 = 채팅 서버 연결 성공
STRING_032 = 채팅 서버 연결 실패
STRING_033 = 채팅 서버 연결 끊김
STRING_034 = 인증 성공
STRING_035 = 인증 실패
STRING_036 = 값이 비어있습니다.
STRING_037 = 관리 서버 연결 성공
STRING_038 = 관리 서버 연결 실패
STRING_039 = 관리 서버 연결 끊김
STRING_040 = 관리 서버 인증 성공
STRING_041 = 채팅 서버 인증
STRING_042 = 관리 서버 인증
STRING_043 = 해당 캐릭터가 존재하지 않습니다.
STRING_044 = 로그인을 해야 사용 가능합니다.
STRING_045 = 유저의 대화 요청!
STRING_046 = 유저의 메세지 받기로 설정한 후 메세지를 보내십시요.
STRING_047 = 현재 로그인 중인 계정
STRING_048 = 유저의 메세지 받기

Binary file not shown.

View File

@@ -0,0 +1,149 @@
// <Release Note>
// 2005-05-25 (ver: 1480.01)
// 1. LOCAL_STRING 섹션에 MSG_063 항목 추가
[CONNECTION]
ManageServerIP = 67.228.215.235
ManageServerPort = 11124
[MISC]
// 기본값: R: 212, G: 208, B: 200
TOOL_BACK_CLR_R =212
TOOL_BACK_CLR_G =208
TOOL_BACK_CLR_B =200
[LOCAL_STRING]
TOTAL_USER_COUNT = 총 유저수:
SHOW_USER_NUM = 유저수 표시
HIDE_USER_NUM = 유저수 숨기기
ALL_SERVER_NOTIFY = 전 서버 공지
STATUS_COLOR = [서버 상태 색]
NORMAL = 정상
SERVER_DOWNED = 서버 다운
DISCONNECTED = 연결 끊김
BLOCKED = 블럭
CLIENT_DOWNED = 관리 클라이언트 다운
PATCH_ONLY = 패치만 가능
LOGIN_CLOSED = 로그인 서버 닫힘
GROUP_STATUS = [그룹 상태 색]
NORMAL_AND_ALL_OPEN = 정상이며 완전 개방
ERROR_OCCURED = 문제 발생
ADMIN_OPEN = 운영자만 개방
ALLOWED_OPEN = 허용된 유저만 개방
CONNECTING_USER_LIST = [접속중인 관리자]
WHO_AM_I = 내 계정:
CURRENT_MANAGER = 관리 권한을 가진 계정:
PROMOTE_ME = 관리 권한 요청
LOGIN_UID_GROUP = [로그인 서버, UID 서버]
SERVER_GROUP_LIST = [서버 그룹 목록]
SELECTED_GROUP_STATUS = [선택된 그룹 상태]
FUNCTION_SERVER = (기능 서버)
SELECTED_SERVER_INFO = (선택된 그룹 정보)
SERVER_GROUP = 서버 그룹:
SERVER_ID = 서버 ID:
HOSTNAME = 호스트 네임:
GAME_ZONE_GROUP = (게임 서버)
GROUP_USER_COUNT = 그룹 유저 수:
REPORT = [리포트]
DISABLE_SOUND_CAUTION = 경고음 사용 안함
DISABLE_REPORT = 리포트 안함
REPORT_LIST = >> 리포트 내용
DELETE = 삭제
ALL_DELETE = 모두 삭제
OPERATION_REPORT = >> 수행 결과
NOTIFY_CONTENTS = [공지 내용]
NOTIFY_TARGET = [공지 대상]
MESSAGE_DELAY = 1라인 공지당 시간 간격:
SEC =
TIME_INTERVAL = 회당 간격:
MIN =
TIMES =
FREQUENCY = 횟수:
NOTIFY = 공지
ADMIN_INFO = 운영자 정보
ADMIN_REG = 운영자 등록
ADMIN_DEL = 운영자 삭제
ADMIN_EDIT = 운영자 정보 수정
ADMIN_MANAGEMENT = 운영자 관리창
LOGIN_NAME_1 = 로우(통합)
LOGIN_NAME_2 = 로우(신규)
LOGIN_NAME_3 = 테스트
STAT_SERVER_STATUS = [통계 서버 상태]
STAT_1ST_STATUS = 1ST 연결
STAT_2ND_STATUS = 2ND 연결
MSG_001 = 로우 서버 관리툴이 초기화 되었습니다!
MSG_002 = 관리 권한을 가지고 있지 않기 때문에 메뉴를 사용할 수 없습니다.
MSG_003 = 접속 오류 - 에러코드-%d
MSG_004 = 서버 명령 실패 - NULL 세션 <※ 관리서버와의 연결상태를 확인하십시요.>
MSG_005 = 잘못된 서버 타입이거나 실행 정보를 얻어오는데 실패했습니다.
MSG_006 = %s 시작 실패 - NULL세션, 에러코드-%d
MSG_007 = %s 시작 실패 - 잘못된 서버 타입이거나 실행 정보를 얻어오는데 실패했습니다, 에러코드-%d
MSG_008 = %s 종료 실패 - NULL 세션, 에러코드-%d
MSG_009 = %s 종료 실패 - 잘못된 서버 타입이거나 실행 정보를 얻어오는제 실패했습니다. 에러코드-%d
MSG_010 = 정말로 강제 종료하시겠습니까?
MSG_011 = %s 프로세스 강제 종료 실패 - NULL 세션, 에러코드-%d
MSG_012 = %s 프로세스 강제 종료 실패 - 잘못된 서버 타입이거나 실행 정보를 얻어오는데 실패했습니다, 에러코드-%d
MSG_013 = 프로세스 강제 종료 취소됨
MSG_014 = 관리 클라이언트 다운
MSG_015 = 서버 다운
MSG_016 = 미디어웹 통합 과금 서버와 연결끊김
MSG_017 = 중계 서버와 연결 끊김
MSG_018 = 채팅 서버와 연결 끊김
MSG_019 = 로그인 서버와 연결 끊김
MSG_020 = UID서버와 연결 끊김
MSG_021 = 서버 블럭
MSG_022 = 관리 권한을 가지고 있지 않습니다.
MSG_023 = 관리 권한이 요청되었습니다. 승인하시겠습니까? (요청자-ID: %s/ Name: %s/ IP: %s)
MSG_024 = 관리 권한을 요청하시겠습니까?
MSG_025 = RunID 맵 셋팅 실패 - RunID를 찾을 수 없습니다. (0x%08X (Group: %d))
MSG_026 = 아직 접속되지 않았습니다. 잠시만 기다려 주세요.
MSG_027 = 접속 성공 - %s:%d
MSG_028 = 접속 실패 - 에러코드-%d
MSG_029 = 세션 연결 끊김
MSG_030 = 관리 서버와 연결이 끊겼습니다.
MSG_031 = 잘못된 RunID 정보입니다. 서버 제어를 할 수 없습니다.
MSG_032 = 인증 성공
MSG_033 = 인증 실패 - 에러코드: %d
MSG_034 = 관리 권한 얻기 성공
MSG_035 = 관리 권한 요청 실패 - 에러코드-%d
MSG_036 = 잘못된 패킷 사이즈 - SS:0x%p/Cmd:0x%p/Size:%d
MSG_037 = 유저 추가 실패 - SS: 0x%p, Cmd:0x%p, Err:%d
MSG_038 = 유저 리스트 얻기 실패 - SS:0x%p, Cmd:0x%p, Err:%d
MSG_039 = 유저 로그인 패킷 얻기 실패 - SS:0x%p, Cmd:0x%p, Err:%d
MSG_040 = 유저 로그아웃 패킷 얻기 실패 - SS:0x%p, Cmd:0x%p, Err:%d
MSG_041 = RunID 정보 얻기 성공. 서버 제어가 가능합니다.
MSG_042 = 프로세스 상태 패킷 얻기 실패 - SS:0x%p, Cmd:0x%p, Err:%d
MSG_043 = 유저리액션 요청 실패 - SS:0x%p, Cmd:0x%p, Err:%d
MSG_044 = 관리자 정보 얻기 실패 - SS:0x%p, Cmd:0x%p, Err:%d
MSG_045 = 등록 할 유저 정보 보내기 실패. 유저 등록 실패.
MSG_046 = 연결이 끊겨 있어서 유저를 등록할 수 없습니다.
MSG_047 = 수정 할 유저 정보 보내기 실패. 유저 정보를 수정 할 수 없습니다.
MSG_048 = 연결이 끊겨 있어서 유저 정보를 수정할 수 없습니다.
MSG_049 = 삭제할 유저 정보 보내기 실패. 유저 삭제 실패.
MSG_050 = 연결이 끊겨 있어서 유저를 삭제할 수 없습니다.
MSG_051 = 운영자 등록창
MSG_052 = 새 운영자 정보
MSG_053 = 운영자 수정창
MSG_054 = 수정 정보
MSG_056 = 공지 성공: %s
MSG_057 = 공지 완료
MSG_058 = 공지 시작
MSG_059 = 메모리 할당 실패로 인해 공지를 보내는데 실패했습니다.
MSG_060 = 공지 메시지 추가 실패: 공지를 보내는데 실패했습니다.
MSG_061 = 공지가 완료되기 전에 창을 닫으면 보내고 있던 공지가 취소됩니다. 그래도 닫으시겠습니까?
MSG_062 = 공지가 취소되었습니다.
MSG_063 = 에러가 있는 패킷 수신 - SS:0x%p, Cmd:0x%p, Err:%d
MSG_064 = 통계서버(1ST) 다운
MSG_065 = 통계서버(2ND) 다운
MSG_066 = 메인 배경색 변경: 색상을 선택한 후 Apply!
MSG_067 = 인증 실패 - 에러코드: %d (이미 로그인되어 있습니다)
MSG_068 = 인증 실패 - 에러코드: %d (존재하지 않는 유저입니다)
MSG_069 = 인증 실패 - 에러코드: %d (패스워드가 일치하지 않습니다)
MSG_070 = 인증 실패 - 에러코드: %d (등록된 IP와 일치하지 않습니다)

View File

@@ -0,0 +1,170 @@
// <Release Note>
// '//'는 주석 표시입니다.
// 2004-07-27
// 1. GENERAL 섹션에 LOGIN_SERVER_NUM 키 추가. 로그인 서버 관리 및 로그인 서버 상태 표시에 영향을 미칩니다.
// 2004-07-28
// 1. 로그인 서버 기능 추가. 로그인 서버 메뉴와 서버 그룹 메뉴에 접속 단계 조절 기능 추가.
// (각 단계별 접속 가능 IP는 매뉴얼 참고)
// 2004-11-03
// 1. STATSERVER_SEND_USER_INFO 섹션을 GLOBAL_STATSERVER_INFO 섹션으로 변경하였습니다.
// 2. 기존에 STATSERVER_SEND_USER_INFO 섹션에 있던 NATION_INDEX 키를 GENERAL 섹션으로 이동했습니다.
// 3. LOCAL_STATSERVER_INFO 섹션이 추가 되었습니다.
// 이 섹션은 한국의 통계서버 이외에 별도의 통계서버를 운영하고자 할때 해당 통계서버의 정보를 설정하시면 됩니다.
// 설정 내용은 GLOBAL_STATSERVER_INFO 섹션과 동일합니다.
// 2005-05-25 (ver: 1480.01)
// 1. GAMESERVER 섹션에 존16 다크 카나번이 추가되었습니다.
// 2. Ping체크 기능이 추가되어서 오래동안 ManageTool과 ManageServer가 핑을 주고 받지 않는 경우 연결이 끊깁니다.
// 3. ManageTool에서 ManageServer와 StatServer의 연결 상태를 확인할 수 있습니다.
// 2005-09-29
// 1. GLOBAL_STATSERVER_INFO와 LOCAL_STATSERVER_INFO를 STATSERVER_INFO로 통합했습니다.
// 2. 기존의 한국, 로컬 두개의 통계서버를 두는 체계에서 한국에만 두개의 통계서버를 두는 형태로 변경되었습니다.
// 3. 셋팅은 특별한 문제가 없는한 항상 두곳(1ST, 2ND)으로 보내도록 셋팅하시면 됩니다.
[GENERAL]
// NATION_INDEX : 국가 코드. 반드시 국가에 맞는 코드로 설정해주세요!
// 한국 = 1
// 대만 = 2
// 중국(북경) = 31, 중국(상해) = 32, 중국(광주) = 33, 중국(성도) = 34
// 태국 = 4
// 말레이시아 = 5
// 인도네시아 = 6, 인도네시아 배틀로한 = 61
// 미국 = 7
// 베트남 = 8
// 일본 = 9
NATION_INDEX = 1
// LOGIN_SERVER_NUM : 관리툴로 관리할 로그인 서버의 갯수
LOGIN_SERVER_NUM = 2
// GAME_CHANNEL_NUM : 게임 채널의 갯수 (구 버전은 단일채널만 지원됩니다)
GAME_CHANNEL_NUM = 1
// #표시는 숫자 생략입니다. 모든 섹션 공통으로 0부터 1씩 차례로 증가하게 셋팅하면 됩니다.
// GAME_CHANNEL_KEY# : 게임 채널 인덱스. 채널인덱스는 0부터 1씩 증가합니다.
// 일반적으로 유저가 보는 1번 채널은 내부 인덱스로 0입니다.
GAME_CHANNEL_KEY0 = 0
// GAME_CHANNEL_STRING# : 해당 게임 채널 명칭. 단순히 알아보기 쉽게 기록하면 됩니다. 예)CH1, Channel1
GAME_CHANNEL_STRING0 = CH1
GAME_CHANNEL_KEY1 = 1
GAME_CHANNEL_STRING1 = CH2
GAME_CHANNEL_KEY2 = 2
GAME_CHANNEL_STRING2 = CH3
[SERVER_TYPE]
// SERVER_TYPE_NUM : 서버 종류의 갯수
SERVER_TYPE_NUM = 8
// SERVER_TYPE_KEY# : 해당 서버 타입의 인덱스. 혹 서버 종류가 늘면 새로 인덱스를 알려드리겠습니다.
SERVER_TYPE_KEY0 = 0
// SERVER_TYPE_STRING# : 해당 서버 타입의 이름.
SERVER_TYPE_STRING0 = Login
SERVER_TYPE_KEY1 = 1
SERVER_TYPE_STRING1 = Auth
SERVER_TYPE_KEY2 = 2
SERVER_TYPE_STRING2 = Game
SERVER_TYPE_KEY3 = 3
SERVER_TYPE_STRING3 = Agent
SERVER_TYPE_KEY4 = 4
SERVER_TYPE_STRING4 = UID
SERVER_TYPE_KEY5 = 5
SERVER_TYPE_STRING5 = Admin
SERVER_TYPE_KEY6 = 6
SERVER_TYPE_STRING6 = Log
SERVER_TYPE_KEY7 = 7
SERVER_TYPE_STRING7 = Chat
[SERVER_GROUP]
// SERVER_GROUP_NUM : 서버 그룹 수
SERVER_GROUP_NUM = 2
// SERVER_GROUP_KEY# : 해당 서버 그룹의 인덱스
SERVER_GROUP_KEY0 = 0
// SERVER_GROUP_STRING# : 해당 서버 그룹의 이름
SERVER_GROUP_STRING0 = 테스트
SERVER_GROUP_KEY1 = 1
SERVER_GROUP_STRING1 = Ichman
//SERVER_GROUP_KEY2 = 2
//SERVER_GROUP_STRING2 = 라타르
//SERVER_GROUP_KEY3 = 3
//SERVER_GROUP_STRING3 = 루안
[GAMESERVER]
// GAME_ZONE_NUM : 게임 존 갯수
GAME_ZONE_NUM = 10
// GAME_ZONE_KEY : 게임존의 인덱스를 뜻합니다. 예) 카나번 = 8, 그랜드 코스트 = 1
GAME_ZONE_KEY0 = 1
// GAME_ZONE_STRING : 해당 존의 이름
GAME_ZONE_STRING0 = Zone1
GAME_ZONE_KEY1 = 2
GAME_ZONE_STRING1 = Zone2
GAME_ZONE_KEY2 = 4
GAME_ZONE_STRING2 = Zone4
GAME_ZONE_KEY3 = 5
GAME_ZONE_STRING3 = Zone5
GAME_ZONE_KEY4 = 8
GAME_ZONE_STRING4 = Zone8
GAME_ZONE_KEY5 = 12
GAME_ZONE_STRING5 = Zone12
GAME_ZONE_KEY6 = 14
GAME_ZONE_STRING6 = Prizon
GAME_ZONE_KEY7 = 16
GAME_ZONE_STRING7 = Zone16
GAME_ZONE_KEY8 = 17
GAME_ZONE_STRING8 = Zone17
GAME_ZONE_KEY9 = 18
GAME_ZONE_STRING9 = Zone18
// 통계 서버 정보
[STATSERVER_INFO]
// SEND_STAT_SERVER_1ST : 첫번째 통계서버로 정보를 보낼지 여부. 1은 보내기이고 1이외의 문자는 보내지 않음.
SEND_STAT_SERVER_1ST = 0
// STAT_SERVER_1ST_IP : 첫번째 통계서버의 아이피 61.251.229.189(한국 Frac 서버)로 셋팅
STAT_SERVER_1ST_IP = 61.251.229.189
// SEND_STAT_SERVER_2ND : 두번째 통계서버로 정보를 보낼지 여부. 1은 보내기이고 1이외의 문자는 보내지 않음.
SEND_STAT_SERVER_2ND = 0
// STAT_SERVER_2ND_IP: 두번째 통계서버의 아이피 61.251.229.187(한국 Fusion 서버)로 셋팅
STAT_SERVER_2ND_IP = 61.251.229.187
// 옵션 셋팅
[SETTING]
// 0: 체크 안함, 1: 체크
USER_IP_CHECK = 0

View File

@@ -0,0 +1,218 @@
<?xml version="1.0" encoding="ks_c_5601-1987"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="GridControl"
ProjectGUID="{EE20E867-1836-4550-A08D-1BBA2F7B2EA3}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../Library/$(ConfigurationName)"
IntermediateDirectory="../Intermediate/$(ProjectName)/$(ConfigurationName)"
ConfigurationType="4"
UseOfMFC="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="3"
WarningLevel="3"
Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/GridControl.lib"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../Library/$(ConfigurationName)"
IntermediateDirectory="../Intermediate/$(ProjectName)/$(ConfigurationName)"
ConfigurationType="4"
UseOfMFC="1"
CharacterSet="2"
WholeProgramOptimization="FALSE">
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
RuntimeLibrary="0"
UsePrecompiledHeader="3"
WarningLevel="3"
Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/GridControl.lib"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="소스 파일"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<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=".\stdafx.h">
</File>
</Filter>
<Filter
Name="리소스 파일"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
</Filter>
<Filter
Name="GridCtrl_src"
Filter="">
<File
RelativePath=".\GridCtrl_src\CellRange.h">
</File>
<File
RelativePath=".\GridCtrl_src\GridCell.cpp">
</File>
<File
RelativePath=".\GridCtrl_src\GridCell.h">
</File>
<File
RelativePath=".\GridCtrl_src\GridCellBase.cpp">
</File>
<File
RelativePath=".\GridCtrl_src\GridCellBase.h">
</File>
<File
RelativePath=".\GridCtrl_src\GridCtrl.cpp">
</File>
<File
RelativePath=".\GridCtrl_src\GridCtrl.h">
</File>
<File
RelativePath=".\GridCtrl_src\GridDropTarget.cpp">
</File>
<File
RelativePath=".\GridCtrl_src\GridDropTarget.h">
</File>
<File
RelativePath=".\GridCtrl_src\InPlaceEdit.cpp">
</File>
<File
RelativePath=".\GridCtrl_src\InPlaceEdit.h">
</File>
<File
RelativePath=".\GridCtrl_src\MemDC.h">
</File>
<File
RelativePath=".\GridCtrl_src\TitleTip.cpp">
</File>
<File
RelativePath=".\GridCtrl_src\TitleTip.h">
</File>
</Filter>
<Filter
Name="NewCellTypes"
Filter="">
<File
RelativePath=".\NewCellTypes\GridCellCheck.cpp">
</File>
<File
RelativePath=".\NewCellTypes\GridCellCheck.h">
</File>
<File
RelativePath=".\NewCellTypes\GridCellCombo.cpp">
</File>
<File
RelativePath=".\NewCellTypes\GridCellCombo.h">
</File>
<File
RelativePath=".\NewCellTypes\GridCellDateTime.cpp">
</File>
<File
RelativePath=".\NewCellTypes\GridCellDateTime.h">
</File>
<File
RelativePath=".\NewCellTypes\GridCellNumeric.cpp">
</File>
<File
RelativePath=".\NewCellTypes\GridCellNumeric.h">
</File>
<File
RelativePath=".\NewCellTypes\GridURLCell.cpp">
</File>
<File
RelativePath=".\NewCellTypes\GridURLCell.h">
</File>
</Filter>
<File
RelativePath=".\ReadMe.txt">
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,148 @@
///////////////////////////////////////////////////////////////////////
// CellRange.h: header file
//
// MFC Grid Control - interface for the CCellRange class.
//
// Written by Chris Maunder <cmaunder@mail.com>
// Copyright (c) 1998-2002. All Rights Reserved.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.20+
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_CELLRANGE_H__F86EF761_725A_11D1_ABBA_00A0243D1382__INCLUDED_)
#define AFX_CELLRANGE_H__F86EF761_725A_11D1_ABBA_00A0243D1382__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// The code contained in this file is based on the original
// WorldCom Grid control written by Joe Willcoxson,
// mailto:chinajoe@aol.com
// http://users.aol.com/chinajoe
class AFX_EXT_CLASS CCellID
{
// Attributes
public:
int row, col;
// Operations
public:
explicit CCellID(int nRow = -1, int nCol = -1) : row(nRow), col(nCol) {}
int IsValid() const { return (row >= 0 && col >= 0); }
int operator==(const CCellID& rhs) const { return (row == rhs.row && col == rhs.col); }
int operator!=(const CCellID& rhs) const { return !operator==(rhs); }
};
class AFX_EXT_CLASS CCellRange
{
public:
CCellRange(int nMinRow = -1, int nMinCol = -1, int nMaxRow = -1, int nMaxCol = -1)
{
Set(nMinRow, nMinCol, nMaxRow, nMaxCol);
}
void Set(int nMinRow = -1, int nMinCol = -1, int nMaxRow = -1, int nMaxCol = -1);
int IsValid() const;
int InRange(int row, int col) const;
int InRange(const CCellID& cellID) const;
int Count() { return (m_nMaxRow - m_nMinRow + 1) * (m_nMaxCol - m_nMinCol + 1); }
CCellID GetTopLeft() const;
CCellRange Intersect(const CCellRange& rhs) const;
int GetMinRow() const {return m_nMinRow;}
void SetMinRow(int minRow) {m_nMinRow = minRow;}
int GetMinCol() const {return m_nMinCol;}
void SetMinCol(int minCol) {m_nMinCol = minCol;}
int GetMaxRow() const {return m_nMaxRow;}
void SetMaxRow(int maxRow) {m_nMaxRow = maxRow;}
int GetMaxCol() const {return m_nMaxCol;}
void SetMaxCol(int maxCol) {m_nMaxCol = maxCol;}
int GetRowSpan() const {return m_nMaxRow - m_nMinRow + 1;}
int GetColSpan() const {return m_nMaxCol - m_nMinCol + 1;}
void operator=(const CCellRange& rhs);
int operator==(const CCellRange& rhs);
int operator!=(const CCellRange& rhs);
protected:
int m_nMinRow;
int m_nMinCol;
int m_nMaxRow;
int m_nMaxCol;
};
inline void CCellRange::Set(int minRow, int minCol, int maxRow, int maxCol)
{
m_nMinRow = minRow;
m_nMinCol = minCol;
m_nMaxRow = maxRow;
m_nMaxCol = maxCol;
}
inline void CCellRange::operator=(const CCellRange& rhs)
{
if (this != &rhs) Set(rhs.m_nMinRow, rhs.m_nMinCol, rhs.m_nMaxRow, rhs.m_nMaxCol);
}
inline int CCellRange::operator==(const CCellRange& rhs)
{
return ((m_nMinRow == rhs.m_nMinRow) && (m_nMinCol == rhs.m_nMinCol) &&
(m_nMaxRow == rhs.m_nMaxRow) && (m_nMaxCol == rhs.m_nMaxCol));
}
inline int CCellRange::operator!=(const CCellRange& rhs)
{
return !operator==(rhs);
}
inline int CCellRange::IsValid() const
{
return (m_nMinRow >= 0 && m_nMinCol >= 0 && m_nMaxRow >= 0 && m_nMaxCol >= 0 &&
m_nMinRow <= m_nMaxRow && m_nMinCol <= m_nMaxCol);
}
inline int CCellRange::InRange(int row, int col) const
{
return (row >= m_nMinRow && row <= m_nMaxRow && col >= m_nMinCol && col <= m_nMaxCol);
}
inline int CCellRange::InRange(const CCellID& cellID) const
{
return InRange(cellID.row, cellID.col);
}
inline CCellID CCellRange::GetTopLeft() const
{
return CCellID(m_nMinRow, m_nMinCol);
}
inline CCellRange CCellRange::Intersect(const CCellRange& rhs) const
{
return CCellRange(max(m_nMinRow,rhs.m_nMinRow), max(m_nMinCol,rhs.m_nMinCol),
min(m_nMaxRow,rhs.m_nMaxRow), min(m_nMaxCol,rhs.m_nMaxCol));
}
#endif // !defined(AFX_CELLRANGE_H__F86EF761_725A_11D1_ABBA_00A0243D1382__INCLUDED_)

View File

@@ -0,0 +1,278 @@
// GridCell.cpp : implementation file
//
// MFC Grid Control - Main grid cell class
//
// Provides the implementation for the "default" cell type of the
// grid control. Adds in cell editing.
//
// Written by Chris Maunder <cmaunder@mail.com>
// Copyright (c) 1998-2002. All Rights Reserved.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.20+
//
// History:
// Eric Woodruff - 20 Feb 2000 - Added PrintCell() plus other minor changes
// Ken Bertelson - 12 Apr 2000 - Split CGridCell into CGridCell and CGridCellBase
// <kenbertelson@hotmail.com>
// C Maunder - 17 Jun 2000 - Font handling optimsed, Added CGridDefaultCell
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "GridCell.h"
#include "InPlaceEdit.h"
#include "GridCtrl.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNCREATE(CGridCell, CGridCellBase)
IMPLEMENT_DYNCREATE(CGridDefaultCell, CGridCell)
/////////////////////////////////////////////////////////////////////////////
// GridCell
CGridCell::CGridCell()
{
m_plfFont = NULL;
CGridCell::Reset();
}
CGridCell::~CGridCell()
{
delete m_plfFont;
}
/////////////////////////////////////////////////////////////////////////////
// GridCell Attributes
void CGridCell::operator=(const CGridCell& cell)
{
if (this != &cell) CGridCellBase::operator=(cell);
}
void CGridCell::Reset()
{
CGridCellBase::Reset();
m_strText.Empty();
m_nImage = -1;
m_pGrid = NULL;
m_bEditing = FALSE;
m_pEditWnd = NULL;
m_nFormat = (DWORD)-1; // Use default from CGridDefaultCell
m_crBkClr = CLR_DEFAULT; // Background colour (or CLR_DEFAULT)
m_crFgClr = CLR_DEFAULT; // Forground colour (or CLR_DEFAULT)
m_nMargin = (UINT)-1; // Use default from CGridDefaultCell
delete m_plfFont;
m_plfFont = NULL; // Cell font
}
void CGridCell::SetFont(const LOGFONT* plf)
{
if (plf == NULL)
{
delete m_plfFont;
m_plfFont = NULL;
}
else
{
if (!m_plfFont)
m_plfFont = new LOGFONT;
if (m_plfFont)
memcpy(m_plfFont, plf, sizeof(LOGFONT));
}
}
LOGFONT* CGridCell::GetFont() const
{
if (m_plfFont == NULL)
{
CGridDefaultCell *pDefaultCell = (CGridDefaultCell*) GetDefaultCell();
if (!pDefaultCell)
return NULL;
return pDefaultCell->GetFont();
}
return m_plfFont;
}
CFont* CGridCell::GetFontObject() const
{
// If the default font is specified, use the default cell implementation
if (m_plfFont == NULL)
{
CGridDefaultCell *pDefaultCell = (CGridDefaultCell*) GetDefaultCell();
if (!pDefaultCell)
return NULL;
return pDefaultCell->GetFontObject();
}
else
{
static CFont Font;
Font.DeleteObject();
Font.CreateFontIndirect(m_plfFont);
return &Font;
}
}
DWORD CGridCell::GetFormat() const
{
if (m_nFormat == (DWORD)-1)
{
CGridDefaultCell *pDefaultCell = (CGridDefaultCell*) GetDefaultCell();
if (!pDefaultCell)
return 0;
return pDefaultCell->GetFormat();
}
return m_nFormat;
}
UINT CGridCell::GetMargin() const
{
if (m_nMargin == (UINT)-1)
{
CGridDefaultCell *pDefaultCell = (CGridDefaultCell*) GetDefaultCell();
if (!pDefaultCell)
return 0;
return pDefaultCell->GetMargin();
}
return m_nMargin;
}
/////////////////////////////////////////////////////////////////////////////
// GridCell Operations
BOOL CGridCell::Edit(int nRow, int nCol, CRect rect, CPoint /* point */, UINT nID, UINT nChar)
{
if ( m_bEditing )
{
if (m_pEditWnd)
m_pEditWnd->SendMessage ( WM_CHAR, nChar );
}
else
{
DWORD dwStyle = ES_LEFT;
if (GetFormat() & DT_RIGHT)
dwStyle = ES_RIGHT;
else if (GetFormat() & DT_CENTER)
dwStyle = ES_CENTER;
m_bEditing = TRUE;
// InPlaceEdit auto-deletes itself
CGridCtrl* pGrid = GetGrid();
m_pEditWnd = new CInPlaceEdit(pGrid, rect, dwStyle, nID, nRow, nCol, GetText(), nChar);
}
return TRUE;
}
void CGridCell::EndEdit()
{
if (m_pEditWnd)
((CInPlaceEdit*)m_pEditWnd)->EndEdit();
}
void CGridCell::OnEndEdit()
{
m_bEditing = FALSE;
m_pEditWnd = NULL;
}
/////////////////////////////////////////////////////////////////////////////
// CGridDefaultCell
CGridDefaultCell::CGridDefaultCell()
{
#ifdef _WIN32_WCE
m_nFormat = DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX;
#else
m_nFormat = DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX | DT_END_ELLIPSIS;
#endif
m_crFgClr = CLR_DEFAULT;
m_crBkClr = CLR_DEFAULT;
m_Size = CSize(30,10);
m_dwStyle = 0;
#ifdef _WIN32_WCE
LOGFONT lf;
GetObject(GetStockObject(SYSTEM_FONT), sizeof(LOGFONT), &lf);
SetFont(&lf);
#else // not CE
NONCLIENTMETRICS ncm;
ncm.cbSize = sizeof(NONCLIENTMETRICS);
VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0));
SetFont(&(ncm.lfMessageFont));
#endif
}
CGridDefaultCell::~CGridDefaultCell()
{
m_Font.DeleteObject();
}
void CGridDefaultCell::SetFont(const LOGFONT* plf)
{
ASSERT(plf);
if (!plf) return;
m_Font.DeleteObject();
m_Font.CreateFontIndirect(plf);
CGridCell::SetFont(plf);
// Get the font size and hence the default cell size
CDC* pDC = CDC::FromHandle(::GetDC(NULL));
if (pDC)
{
CFont* pOldFont = pDC->SelectObject(&m_Font);
SetMargin(pDC->GetTextExtent(_T(" "), 1).cx);
m_Size = pDC->GetTextExtent(_T(" XXXXXXXXXXXX "), 14);
m_Size.cy = (m_Size.cy * 3) / 2;
pDC->SelectObject(pOldFont);
ReleaseDC(NULL, pDC->GetSafeHdc());
}
else
{
SetMargin(3);
m_Size = CSize(40,16);
}
}
LOGFONT* CGridDefaultCell::GetFont() const
{
ASSERT(m_plfFont); // This is the default - it CAN'T be NULL!
return m_plfFont;
}
CFont* CGridDefaultCell::GetFontObject() const
{
ASSERT(m_Font.GetSafeHandle());
return (CFont*) &m_Font;
}

View File

@@ -0,0 +1,143 @@
/////////////////////////////////////////////////////////////////////////////
// GridCell.h : header file
//
// MFC Grid Control - Grid cell class header file
//
// Written by Chris Maunder <cmaunder@mail.com>
// Copyright (c) 1998-2002. All Rights Reserved.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.20+
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_GRIDCELL_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_)
#define AFX_GRIDCELL_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
class CGridCtrl;
#include "GridCellBase.h"
// Each cell contains one of these. Fields "row" and "column" are not stored since we
// will usually have acces to them in other ways, and they are an extra 8 bytes per
// cell that is probably unnecessary.
class AFX_EXT_CLASS CGridCell : public CGridCellBase
{
friend class CGridCtrl;
DECLARE_DYNCREATE(CGridCell)
// Construction/Destruction
public:
CGridCell();
virtual ~CGridCell();
// Attributes
public:
void operator=(const CGridCell& cell);
virtual void SetText(LPCTSTR szText) { m_strText = szText; }
virtual void SetImage(int nImage) { m_nImage = nImage; }
virtual void SetData(LPARAM lParam) { m_lParam = lParam; }
virtual void SetGrid(CGridCtrl* pGrid) { m_pGrid = pGrid; }
// virtual void SetState(const DWORD nState); - use base class version
virtual void SetFormat(DWORD nFormat) { m_nFormat = nFormat; }
virtual void SetTextClr(COLORREF clr) { m_crFgClr = clr; }
virtual void SetBackClr(COLORREF clr) { m_crBkClr = clr; }
virtual void SetFont(const LOGFONT* plf);
virtual void SetMargin(UINT nMargin) { m_nMargin = nMargin; }
virtual CWnd* GetEditWnd() const { return m_pEditWnd; }
virtual void SetCoords(int /*nRow*/, int /*nCol*/) {} // don't need to know the row and
// column for base implementation
virtual LPCTSTR GetText() const { return (m_strText.IsEmpty())? _T("") : LPCTSTR(m_strText); }
virtual int GetImage() const { return m_nImage; }
virtual LPARAM GetData() const { return m_lParam; }
virtual CGridCtrl* GetGrid() const { return m_pGrid; }
// virtual DWORD GetState() const - use base class
virtual DWORD GetFormat() const;
virtual COLORREF GetTextClr() const { return m_crFgClr; } // TODO: change to use default cell
virtual COLORREF GetBackClr() const { return m_crBkClr; }
virtual LOGFONT* GetFont() const;
virtual CFont* GetFontObject() const;
virtual UINT GetMargin() const;
virtual BOOL IsEditing() const { return m_bEditing; }
virtual BOOL IsDefaultFont() const { return (m_plfFont == NULL); }
virtual void Reset();
// editing cells
public:
virtual BOOL Edit(int nRow, int nCol, CRect rect, CPoint point, UINT nID, UINT nChar);
virtual void EndEdit();
protected:
virtual void OnEndEdit();
protected:
CString m_strText; // Cell text (or binary data if you wish...)
LPARAM m_lParam; // 32-bit value to associate with item
int m_nImage; // Index of the list view items icon
DWORD m_nFormat;
COLORREF m_crFgClr;
COLORREF m_crBkClr;
LOGFONT* m_plfFont;
UINT m_nMargin;
BOOL m_bEditing; // Cell being edited?
CGridCtrl* m_pGrid; // Parent grid control
CWnd* m_pEditWnd;
};
// This class is for storing grid default values. It's a little heavy weight, so
// don't use it in bulk
class AFX_EXT_CLASS CGridDefaultCell : public CGridCell
{
DECLARE_DYNCREATE(CGridDefaultCell)
// Construction/Destruction
public:
CGridDefaultCell();
virtual ~CGridDefaultCell();
public:
virtual DWORD GetStyle() const { return m_dwStyle; }
virtual void SetStyle(DWORD dwStyle) { m_dwStyle = dwStyle; }
virtual int GetWidth() const { return m_Size.cx; }
virtual int GetHeight() const { return m_Size.cy; }
virtual void SetWidth(int nWidth) { m_Size.cx = nWidth; }
virtual void SetHeight(int nHeight) { m_Size.cy = nHeight; }
// Disable these properties
virtual void SetData(LPARAM /*lParam*/) { ASSERT(FALSE); }
virtual void SetState(DWORD /*nState*/) { ASSERT(FALSE); }
virtual DWORD GetState() const { return CGridCell::GetState()|GVIS_READONLY; }
virtual void SetCoords( int /*row*/, int /*col*/) { ASSERT(FALSE); }
virtual void SetFont(const LOGFONT* /*plf*/);
virtual LOGFONT* GetFont() const;
virtual CFont* GetFontObject() const;
protected:
CSize m_Size; // Default Size
CFont m_Font; // Cached font
DWORD m_dwStyle; // Cell Style - unused
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_GRIDCELL_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_)

View File

@@ -0,0 +1,749 @@
// GridCellBase.cpp : implementation file
//
// MFC Grid Control - Main grid cell base class
//
// Provides the implementation for the base cell type of the
// grid control. No data is stored (except for state) but default
// implementations of drawing, printingetc provided. MUST be derived
// from to be used.
//
// Written by Chris Maunder <cmaunder@mail.com>
// Copyright (c) 1998-2002. All Rights Reserved.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.22+
//
// History:
// Ken Bertelson - 12 Apr 2000 - Split CGridCell into CGridCell and CGridCellBase
// C Maunder - 19 May 2000 - Fixed sort arrow drawing (Ivan Ilinov)
// C Maunder - 29 Aug 2000 - operator= checks for NULL font before setting (Martin Richter)
// C Maunder - 15 Oct 2000 - GetTextExtent fixed (Martin Richter)
// C Maunder - 1 Jan 2001 - Added ValidateEdit
//
// NOTES: Each grid cell should take care of it's own drawing, though the Draw()
// method takes an "erase background" paramter that is called if the grid
// decides to draw the entire grid background in on hit. Certain ambient
// properties such as the default font to use, and hints on how to draw
// fixed cells should be fetched from the parent grid. The grid trusts the
// cells will behave in a certain way, and the cells trust the grid will
// supply accurate information.
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "GridCtrl.h"
#include "GridCellBase.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNAMIC(CGridCellBase, CObject)
/////////////////////////////////////////////////////////////////////////////
// GridCellBase
CGridCellBase::CGridCellBase()
{
Reset();
}
CGridCellBase::~CGridCellBase()
{
}
/////////////////////////////////////////////////////////////////////////////
// GridCellBase Operations
void CGridCellBase::Reset()
{
m_nState = 0;
}
void CGridCellBase::operator=(const CGridCellBase& cell)
{
if (this == &cell) return;
SetGrid(cell.GetGrid()); // do first in case of dependencies
SetText(cell.GetText());
SetImage(cell.GetImage());
SetData(cell.GetData());
SetState(cell.GetState());
SetFormat(cell.GetFormat());
SetTextClr(cell.GetTextClr());
SetBackClr(cell.GetBackClr());
SetFont(cell.IsDefaultFont()? NULL : cell.GetFont());
SetMargin(cell.GetMargin());
}
/////////////////////////////////////////////////////////////////////////////
// CGridCellBase Attributes
// Returns a pointer to a cell that holds default values for this particular type of cell
CGridCellBase* CGridCellBase::GetDefaultCell() const
{
if (GetGrid())
return GetGrid()->GetDefaultCell(IsFixedRow(), IsFixedCol());
return NULL;
}
/////////////////////////////////////////////////////////////////////////////
// CGridCellBase Operations
// EFW - Various changes to make it draw cells better when using alternate
// color schemes. Also removed printing references as that's now done
// by PrintCell() and fixed the sort marker so that it doesn't draw out
// of bounds.
BOOL CGridCellBase::Draw(CDC* pDC, int nRow, int nCol, CRect rect, BOOL bEraseBkgnd /*=TRUE*/)
{
// Note - all through this function we totally brutalise 'rect'. Do not
// depend on it's value being that which was passed in.
CGridCtrl* pGrid = GetGrid();
ASSERT(pGrid);
if (!pGrid || !pDC)
return FALSE;
if( rect.Width() <= 0 || rect.Height() <= 0) // prevents imagelist item from drawing even
return FALSE; // though cell is hidden
//TRACE3("Drawing %scell %d, %d\n", IsFixed()? _T("Fixed ") : _T(""), nRow, nCol);
int nSavedDC = pDC->SaveDC();
pDC->SetBkMode(TRANSPARENT);
// Get the default cell implementation for this kind of cell. We use it if this cell
// has anything marked as "default"
CGridDefaultCell *pDefaultCell = (CGridDefaultCell*) GetDefaultCell();
if (!pDefaultCell)
return FALSE;
// Set up text and background colours
COLORREF TextClr, TextBkClr;
TextClr = (GetTextClr() == CLR_DEFAULT)? pDefaultCell->GetTextClr() : GetTextClr();
if (GetBackClr() == CLR_DEFAULT)
TextBkClr = pDefaultCell->GetBackClr();
else
{
bEraseBkgnd = TRUE;
TextBkClr = GetBackClr();
}
// Draw cell background and highlighting (if necessary)
if ( IsFocused() || IsDropHighlighted() )
{
// Always draw even in list mode so that we can tell where the
// cursor is at. Use the highlight colors though.
if(GetState() & GVIS_SELECTED)
{
TextBkClr = ::GetSysColor(COLOR_HIGHLIGHT);
TextClr = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
bEraseBkgnd = TRUE;
}
rect.right++; rect.bottom++; // FillRect doesn't draw RHS or bottom
if (bEraseBkgnd)
{
TRY
{
CBrush brush(TextBkClr);
pDC->FillRect(rect, &brush);
}
CATCH(CResourceException, e)
{
//e->ReportError();
}
END_CATCH
}
// Don't adjust frame rect if no grid lines so that the
// whole cell is enclosed.
if(pGrid->GetGridLines() != GVL_NONE)
{
rect.right--;
rect.bottom--;
}
if (pGrid->GetFrameFocusCell())
{
// Use same color as text to outline the cell so that it shows
// up if the background is black.
TRY
{
CBrush brush(TextClr);
pDC->FrameRect(rect, &brush);
}
CATCH(CResourceException, e)
{
//e->ReportError();
}
END_CATCH
}
pDC->SetTextColor(TextClr);
// Adjust rect after frame draw if no grid lines
if(pGrid->GetGridLines() == GVL_NONE)
{
rect.right--;
rect.bottom--;
}
rect.DeflateRect(0,1,1,1);
}
else if ((GetState() & GVIS_SELECTED))
{
rect.right++; rect.bottom++; // FillRect doesn't draw RHS or bottom
pDC->FillSolidRect(rect, ::GetSysColor(COLOR_HIGHLIGHT));
rect.right--; rect.bottom--;
pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
}
else
{
if (bEraseBkgnd)
{
rect.right++; rect.bottom++; // FillRect doesn't draw RHS or bottom
CBrush brush(TextBkClr);
pDC->FillRect(rect, &brush);
rect.right--; rect.bottom--;
}
pDC->SetTextColor(TextClr);
}
// Draw lines only when wanted
if (IsFixed() && pGrid->GetGridLines() != GVL_NONE)
{
CCellID FocusCell = pGrid->GetFocusCell();
// As above, always show current location even in list mode so
// that we know where the cursor is at.
BOOL bHiliteFixed = pGrid->GetTrackFocusCell() && pGrid->IsValid(FocusCell) &&
(FocusCell.row == nRow || FocusCell.col == nCol);
// If this fixed cell is on the same row/col as the focus cell,
// highlight it.
if (bHiliteFixed)
{
rect.right++; rect.bottom++;
pDC->DrawEdge(rect, BDR_SUNKENINNER /*EDGE_RAISED*/, BF_RECT);
rect.DeflateRect(1,1);
}
else
{
CPen lightpen(PS_SOLID, 1, ::GetSysColor(COLOR_3DHIGHLIGHT)),
darkpen(PS_SOLID, 1, ::GetSysColor(COLOR_3DDKSHADOW)),
*pOldPen = pDC->GetCurrentPen();
pDC->SelectObject(&lightpen);
pDC->MoveTo(rect.right, rect.top);
pDC->LineTo(rect.left, rect.top);
pDC->LineTo(rect.left, rect.bottom);
pDC->SelectObject(&darkpen);
pDC->MoveTo(rect.right, rect.top);
pDC->LineTo(rect.right, rect.bottom);
pDC->LineTo(rect.left, rect.bottom);
pDC->SelectObject(pOldPen);
rect.DeflateRect(1,1);
}
}
// Draw Text and image
#if !defined(_WIN32_WCE_NO_PRINTING) && !defined(GRIDCONTROL_NO_PRINTING)
if (!pDC->m_bPrinting)
#endif
{
CFont *pFont = GetFontObject();
ASSERT(pFont);
if (pFont)
pDC->SelectObject(pFont);
}
rect.DeflateRect(GetMargin(), 0);
if (pGrid->GetImageList() && GetImage() >= 0)
{
IMAGEINFO Info;
if (pGrid->GetImageList()->GetImageInfo(GetImage(), &Info))
{
// would like to use a clipping region but seems to have issue
// working with CMemDC directly. Instead, don't display image
// if any part of it cut-off
//
// CRgn rgn;
// rgn.CreateRectRgnIndirect(rect);
// pDC->SelectClipRgn(&rgn);
// rgn.DeleteObject();
int nImageWidth = Info.rcImage.right-Info.rcImage.left+1;
int nImageHeight = Info.rcImage.bottom-Info.rcImage.top+1;
if( nImageWidth + rect.left <= rect.right + (int)(2*GetMargin())
&& nImageHeight + rect.top <= rect.bottom + (int)(2*GetMargin()) )
{
pGrid->GetImageList()->Draw(pDC, GetImage(), rect.TopLeft(), ILD_NORMAL);
}
//rect.left += nImageWidth+GetMargin();
}
}
// Draw sort arrow
if (pGrid->GetSortColumn() == nCol && nRow == 0)
{
CSize size = pDC->GetTextExtent(_T("M"));
int nOffset = 2;
// Base the size of the triangle on the smaller of the column
// height or text height with a slight offset top and bottom.
// Otherwise, it can get drawn outside the bounds of the cell.
size.cy -= (nOffset * 2);
if (size.cy >= rect.Height())
size.cy = rect.Height() - (nOffset * 2);
size.cx = size.cy; // Make the dimensions square
// Kludge for vertical text
BOOL bVertical = (GetFont()->lfEscapement == 900);
// Only draw if it'll fit!
if (size.cx + rect.left < rect.right + (int)(2*GetMargin()))
{
int nTriangleBase = rect.bottom - nOffset - size.cy; // Triangle bottom right
//int nTriangleBase = (rect.top + rect.bottom - size.cy)/2; // Triangle middle right
//int nTriangleBase = rect.top + nOffset; // Triangle top right
//int nTriangleLeft = rect.right - size.cx; // Triangle RHS
//int nTriangleLeft = (rect.right + rect.left - size.cx)/2; // Triangle middle
//int nTriangleLeft = rect.left; // Triangle LHS
int nTriangleLeft;
if (bVertical)
nTriangleLeft = (rect.right + rect.left - size.cx)/2; // Triangle middle
else
nTriangleLeft = rect.right - size.cx; // Triangle RHS
CPen penShadow(PS_SOLID, 0, ::GetSysColor(COLOR_3DSHADOW));
CPen penLight(PS_SOLID, 0, ::GetSysColor(COLOR_3DHILIGHT));
if (pGrid->GetSortAscending())
{
// Draw triangle pointing upwards
CPen *pOldPen = (CPen*) pDC->SelectObject(&penLight);
pDC->MoveTo( nTriangleLeft + 1, nTriangleBase + size.cy + 1);
pDC->LineTo( nTriangleLeft + (size.cx / 2) + 1, nTriangleBase + 1 );
pDC->LineTo( nTriangleLeft + size.cx + 1, nTriangleBase + size.cy + 1);
pDC->LineTo( nTriangleLeft + 1, nTriangleBase + size.cy + 1);
pDC->SelectObject(&penShadow);
pDC->MoveTo( nTriangleLeft, nTriangleBase + size.cy );
pDC->LineTo( nTriangleLeft + (size.cx / 2), nTriangleBase );
pDC->LineTo( nTriangleLeft + size.cx, nTriangleBase + size.cy );
pDC->LineTo( nTriangleLeft, nTriangleBase + size.cy );
pDC->SelectObject(pOldPen);
}
else
{
// Draw triangle pointing downwards
CPen *pOldPen = (CPen*) pDC->SelectObject(&penLight);
pDC->MoveTo( nTriangleLeft + 1, nTriangleBase + 1 );
pDC->LineTo( nTriangleLeft + (size.cx / 2) + 1, nTriangleBase + size.cy + 1 );
pDC->LineTo( nTriangleLeft + size.cx + 1, nTriangleBase + 1 );
pDC->LineTo( nTriangleLeft + 1, nTriangleBase + 1 );
pDC->SelectObject(&penShadow);
pDC->MoveTo( nTriangleLeft, nTriangleBase );
pDC->LineTo( nTriangleLeft + (size.cx / 2), nTriangleBase + size.cy );
pDC->LineTo( nTriangleLeft + size.cx, nTriangleBase );
pDC->LineTo( nTriangleLeft, nTriangleBase );
pDC->SelectObject(pOldPen);
}
if (!bVertical)
rect.right -= size.cy;
}
}
// We want to see '&' characters so use DT_NOPREFIX
GetTextRect(rect);
DrawText(pDC->m_hDC, GetText(), -1, rect, GetFormat() | DT_NOPREFIX);
pDC->RestoreDC(nSavedDC);
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CGridCellBase Mouse and Cursor events
// Not yet implemented
void CGridCellBase::OnMouseEnter()
{
TRACE0("Mouse entered cell\n");
}
void CGridCellBase::OnMouseOver()
{
//TRACE0("Mouse over cell\n");
}
// Not Yet Implemented
void CGridCellBase::OnMouseLeave()
{
TRACE0("Mouse left cell\n");
}
void CGridCellBase::OnClick( CPoint PointCellRelative)
{
UNUSED_ALWAYS(PointCellRelative);
TRACE2("Mouse Left btn up in cell at x=%i y=%i\n", PointCellRelative.x, PointCellRelative.y);
}
void CGridCellBase::OnClickDown( CPoint PointCellRelative)
{
UNUSED_ALWAYS(PointCellRelative);
TRACE2("Mouse Left btn down in cell at x=%i y=%i\n", PointCellRelative.x, PointCellRelative.y);
}
void CGridCellBase::OnRClick( CPoint PointCellRelative)
{
UNUSED_ALWAYS(PointCellRelative);
TRACE2("Mouse right-clicked in cell at x=%i y=%i\n", PointCellRelative.x, PointCellRelative.y);
}
void CGridCellBase::OnDblClick( CPoint PointCellRelative)
{
UNUSED_ALWAYS(PointCellRelative);
TRACE2("Mouse double-clicked in cell at x=%i y=%i\n", PointCellRelative.x, PointCellRelative.y);
}
// Return TRUE if you set the cursor
BOOL CGridCellBase::OnSetCursor()
{
#ifndef _WIN32_WCE_NO_CURSOR
SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
#endif
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CGridCellBase editing
void CGridCellBase::OnEndEdit()
{
ASSERT( FALSE);
}
BOOL CGridCellBase::ValidateEdit(LPCTSTR str)
{
UNUSED_ALWAYS(str);
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CGridCellBase Sizing
BOOL CGridCellBase::GetTextRect( LPRECT pRect) // i/o: i=dims of cell rect; o=dims of text rect
{
if (GetImage() >= 0)
{
IMAGEINFO Info;
CGridCtrl* pGrid = GetGrid();
CImageList* pImageList = pGrid->GetImageList();
if (pImageList && pImageList->GetImageInfo( GetImage(), &Info))
{
int nImageWidth = Info.rcImage.right-Info.rcImage.left+1;
pRect->left += nImageWidth + GetMargin();
}
}
return TRUE;
}
// By default this uses the selected font (which is a bigger font)
CSize CGridCellBase::GetTextExtent(LPCTSTR szText, CDC* pDC /*= NULL*/)
{
CGridCtrl* pGrid = GetGrid();
ASSERT(pGrid);
BOOL bReleaseDC = FALSE;
if (pDC == NULL || szText == NULL)
{
if (szText)
pDC = pGrid->GetDC();
if (pDC == NULL || szText == NULL)
{
CGridDefaultCell* pDefCell = (CGridDefaultCell*) GetDefaultCell();
ASSERT(pDefCell);
return CSize(pDefCell->GetWidth(), pDefCell->GetHeight());
}
bReleaseDC = TRUE;
}
CFont *pOldFont = NULL,
*pFont = GetFontObject();
if (pFont)
pOldFont = pDC->SelectObject(pFont);
CSize size;
int nFormat = GetFormat();
// If the cell is a multiline cell, then use the width of the cell
// to get the height
if ((nFormat & DT_WORDBREAK) && !(nFormat & DT_SINGLELINE))
{
CString str = szText;
int nMaxWidth = 0;
while (TRUE)
{
int nPos = str.Find(_T('\n'));
CString TempStr = (nPos < 0)? str : str.Left(nPos);
int nTempWidth = pDC->GetTextExtent(TempStr).cx;
if (nTempWidth > nMaxWidth)
nMaxWidth = nTempWidth;
if (nPos < 0)
break;
str = str.Mid(nPos + 1); // Bug fix by Thomas Steinborn
}
CRect rect;
rect.SetRect(0,0, nMaxWidth+1, 0);
pDC->DrawText(szText, -1, rect, nFormat | DT_CALCRECT);
size = rect.Size();
}
else
size = pDC->GetTextExtent(szText, _tcslen(szText));
TEXTMETRIC tm;
pDC->GetTextMetrics(&tm);
size.cx += (tm.tmOverhang);
if (pOldFont)
pDC->SelectObject(pOldFont);
size += CSize(4*GetMargin(), 2*GetMargin());
// Kludge for vertical text
LOGFONT *pLF = GetFont();
if (pLF->lfEscapement == 900 || pLF->lfEscapement == -900)
{
int nTemp = size.cx;
size.cx = size.cy;
size.cy = nTemp;
size += CSize(0, 4*GetMargin());
}
if (bReleaseDC)
pGrid->ReleaseDC(pDC);
return size;
}
CSize CGridCellBase::GetCellExtent(CDC* pDC)
{
CSize size = GetTextExtent(GetText(), pDC);
CSize ImageSize(0,0);
int nImage = GetImage();
if (nImage >= 0)
{
CGridCtrl* pGrid = GetGrid();
ASSERT(pGrid);
if (pGrid->GetImageList())
{
IMAGEINFO Info;
if (pGrid->GetImageList()->GetImageInfo(nImage, &Info))
ImageSize = CSize(Info.rcImage.right-Info.rcImage.left+1,
Info.rcImage.bottom-Info.rcImage.top+1);
}
}
return CSize(size.cx + ImageSize.cx, max(size.cy, ImageSize.cy));
}
// EFW - Added to print cells so that grids that use different colors are
// printed correctly.
BOOL CGridCellBase::PrintCell(CDC* pDC, int /*nRow*/, int /*nCol*/, CRect rect)
{
#if defined(_WIN32_WCE_NO_PRINTING) || defined(GRIDCONTROL_NO_PRINTING)
return FALSE;
#else
COLORREF crFG, crBG;
GV_ITEM Item;
CGridCtrl* pGrid = GetGrid();
if (!pGrid || !pDC)
return FALSE;
if( rect.Width() <= 0
|| rect.Height() <= 0) // prevents imagelist item from drawing even
return FALSE; // though cell is hidden
int nSavedDC = pDC->SaveDC();
pDC->SetBkMode(TRANSPARENT);
if (pGrid->GetShadedPrintOut())
{
// Get the default cell implementation for this kind of cell. We use it if this cell
// has anything marked as "default"
CGridDefaultCell *pDefaultCell = (CGridDefaultCell*) GetDefaultCell();
if (!pDefaultCell)
return FALSE;
// Use custom color if it doesn't match the default color and the
// default grid background color. If not, leave it alone.
if(IsFixed())
crBG = (GetBackClr() != CLR_DEFAULT) ? GetBackClr() : pDefaultCell->GetBackClr();
else
crBG = (GetBackClr() != CLR_DEFAULT && GetBackClr() != pDefaultCell->GetBackClr()) ?
GetBackClr() : CLR_DEFAULT;
// Use custom color if the background is different or if it doesn't
// match the default color and the default grid text color.
if(IsFixed())
crFG = (GetBackClr() != CLR_DEFAULT) ? GetTextClr() : pDefaultCell->GetTextClr();
else
crFG = (GetBackClr() != CLR_DEFAULT) ? GetTextClr() : pDefaultCell->GetTextClr();
// If not printing on a color printer, adjust the foreground color
// to a gray scale if the background color isn't used so that all
// colors will be visible. If not, some colors turn to solid black
// or white when printed and may not show up. This may be caused by
// coarse dithering by the printer driver too (see image note below).
if(pDC->GetDeviceCaps(NUMCOLORS) == 2 && crBG == CLR_DEFAULT)
crFG = RGB(GetRValue(crFG) * 0.30, GetGValue(crFG) * 0.59,
GetBValue(crFG) * 0.11);
// Only erase the background if the color is not the default
// grid background color.
if(crBG != CLR_DEFAULT)
{
CBrush brush(crBG);
rect.right++; rect.bottom++;
pDC->FillRect(rect, &brush);
rect.right--; rect.bottom--;
}
}
else
{
crBG = CLR_DEFAULT;
crFG = RGB(0, 0, 0);
}
pDC->SetTextColor(crFG);
CFont *pFont = GetFontObject();
if (pFont)
pDC->SelectObject(pFont);
/*
// ***************************************************
// Disabled - if you need this functionality then you'll need to rewrite.
// Create the appropriate font and select into DC.
CFont Font;
// Bold the fixed cells if not shading the print out. Use italic
// font it it is enabled.
const LOGFONT* plfFont = GetFont();
if(IsFixed() && !pGrid->GetShadedPrintOut())
{
Font.CreateFont(plfFont->lfHeight, 0, 0, 0, FW_BOLD, plfFont->lfItalic, 0, 0,
ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
#ifndef _WIN32_WCE
PROOF_QUALITY,
#else
DEFAULT_QUALITY,
#endif
VARIABLE_PITCH | FF_SWISS, plfFont->lfFaceName);
}
else
Font.CreateFontIndirect(plfFont);
pDC->SelectObject(&Font);
// ***************************************************
*/
// Draw lines only when wanted on fixed cells. Normal cell grid lines
// are handled in OnPrint.
if(pGrid->GetGridLines() != GVL_NONE && IsFixed())
{
CPen lightpen(PS_SOLID, 1, ::GetSysColor(COLOR_3DHIGHLIGHT)),
darkpen(PS_SOLID, 1, ::GetSysColor(COLOR_3DDKSHADOW)),
*pOldPen = pDC->GetCurrentPen();
pDC->SelectObject(&lightpen);
pDC->MoveTo(rect.right, rect.top);
pDC->LineTo(rect.left, rect.top);
pDC->LineTo(rect.left, rect.bottom);
pDC->SelectObject(&darkpen);
pDC->MoveTo(rect.right, rect.top);
pDC->LineTo(rect.right, rect.bottom);
pDC->LineTo(rect.left, rect.bottom);
rect.DeflateRect(1,1);
pDC->SelectObject(pOldPen);
}
rect.DeflateRect(GetMargin(), 0);
if(pGrid->GetImageList() && GetImage() >= 0)
{
// NOTE: If your printed images look like fuzzy garbage, check the
// settings on your printer driver. If it's using coarse
// dithering and/or vector graphics, they may print wrong.
// Changing to fine dithering and raster graphics makes them
// print properly. My HP 4L had that problem.
IMAGEINFO Info;
if(pGrid->GetImageList()->GetImageInfo(GetImage(), &Info))
{
int nImageWidth = Info.rcImage.right-Info.rcImage.left;
pGrid->GetImageList()->Draw(pDC, GetImage(), rect.TopLeft(), ILD_NORMAL);
rect.left += nImageWidth+GetMargin();
}
}
// Draw without clipping so as not to lose text when printed for real
// DT_NOCLIP removed 01.01.01. Slower, but who cares - we are printing!
DrawText(pDC->m_hDC, GetText(), -1, rect,
GetFormat() | /*DT_NOCLIP | */ DT_NOPREFIX);
pDC->RestoreDC(nSavedDC);
return TRUE;
#endif
}
/*****************************************************************************
Callable by derived classes, only
*****************************************************************************/
LRESULT CGridCellBase::SendMessageToParent(int nRow, int nCol, int nMessage)
{
CGridCtrl* pGrid = GetGrid();
if( pGrid)
return pGrid->SendMessageToParent(nRow, nCol, nMessage);
else
return 0;
}

View File

@@ -0,0 +1,172 @@
/////////////////////////////////////////////////////////////////////////////
// GridCellBase.h : header file
//
// MFC Grid Control - Grid cell base class header file
//
// Written by Chris Maunder <cmaunder@mail.com>
// Copyright (c) 1998-2002. All Rights Reserved.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.22+
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_GRIDCELLBASE_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_)
#define AFX_GRIDCELLBASE_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
class CGridCtrl;
// Cell states
#define GVIS_FOCUSED 0x0001
#define GVIS_SELECTED 0x0002
#define GVIS_DROPHILITED 0x0004
#define GVIS_READONLY 0x0008
#define GVIS_FIXED 0x0010
#define GVIS_FIXEDROW 0x0020
#define GVIS_FIXEDCOL 0x0040
#define GVIS_MODIFIED 0x0080
// Cell data mask
#define GVIF_TEXT LVIF_TEXT
#define GVIF_IMAGE LVIF_IMAGE
#define GVIF_PARAM LVIF_PARAM
#define GVIF_STATE LVIF_STATE
#define GVIF_BKCLR (GVIF_STATE<<1)
#define GVIF_FGCLR (GVIF_STATE<<2)
#define GVIF_FORMAT (GVIF_STATE<<3)
#define GVIF_FONT (GVIF_STATE<<4)
#define GVIF_MARGIN (GVIF_STATE<<5)
#define GVIF_ALL (GVIF_TEXT|GVIF_IMAGE|GVIF_PARAM|GVIF_STATE|GVIF_BKCLR|GVIF_FGCLR| \
GVIF_FORMAT|GVIF_FONT|GVIF_MARGIN)
// Used for Get/SetItem calls.
typedef struct _GV_ITEM {
int row,col; // Row and Column of item
UINT mask; // Mask for use in getting/setting cell data
UINT nState; // cell state (focus/hilighted etc)
DWORD nFormat; // Format of cell
int iImage; // index of the list view items icon
COLORREF crBkClr; // Background colour (or CLR_DEFAULT)
COLORREF crFgClr; // Forground colour (or CLR_DEFAULT)
LPARAM lParam; // 32-bit value to associate with item
LOGFONT lfFont; // Cell font
UINT nMargin; // Internal cell margin
CString strText; // Text in cell
} GV_ITEM;
// Each cell contains one of these. Fields "row" and "column" are not stored since we
// will usually have acces to them in other ways, and they are an extra 8 bytes per
// cell that is probably unnecessary.
class AFX_EXT_CLASS CGridCellBase : public CObject
{
friend class CGridCtrl;
DECLARE_DYNAMIC(CGridCellBase)
// Construction/Destruction
public:
CGridCellBase();
virtual ~CGridCellBase();
// Attributes
public:
virtual void SetText(LPCTSTR /* szText */) = 0 ;
virtual void SetImage(int /* nImage */) = 0 ;
virtual void SetData(LPARAM /* lParam */) = 0 ;
virtual void SetState(DWORD nState) { m_nState = nState; }
virtual void SetFormat(DWORD /* nFormat */) = 0 ;
virtual void SetTextClr(COLORREF /* clr */) = 0 ;
virtual void SetBackClr(COLORREF /* clr */) = 0 ;
virtual void SetFont(const LOGFONT* /* plf */) = 0 ;
virtual void SetMargin( UINT /* nMargin */) = 0 ;
virtual void SetGrid(CGridCtrl* /* pGrid */) = 0 ;
virtual void SetCoords( int /* nRow */, int /* nCol */) = 0 ;
virtual LPCTSTR GetText() const = 0 ;
virtual LPCTSTR GetTipText() const { return GetText(); } // may override TitleTip return
virtual int GetImage() const = 0 ;
virtual LPARAM GetData() const = 0 ;
virtual DWORD GetState() const { return m_nState; }
virtual DWORD GetFormat() const = 0 ;
virtual COLORREF GetTextClr() const = 0 ;
virtual COLORREF GetBackClr() const = 0 ;
virtual LOGFONT * GetFont() const = 0 ;
virtual CFont * GetFontObject() const = 0 ;
virtual CGridCtrl* GetGrid() const = 0 ;
virtual CWnd * GetEditWnd() const = 0 ;
virtual UINT GetMargin() const = 0 ;
virtual CGridCellBase* GetDefaultCell() const;
virtual BOOL IsDefaultFont() const = 0 ;
virtual BOOL IsEditing() const = 0 ;
virtual BOOL IsFocused() const { return (m_nState & GVIS_FOCUSED); }
virtual BOOL IsFixed() const { return (m_nState & GVIS_FIXED); }
virtual BOOL IsFixedCol() const { return (m_nState & GVIS_FIXEDCOL); }
virtual BOOL IsFixedRow() const { return (m_nState & GVIS_FIXEDROW); }
virtual BOOL IsSelected() const { return (m_nState & GVIS_SELECTED); }
virtual BOOL IsReadOnly() const { return (m_nState & GVIS_READONLY); }
virtual BOOL IsModified() const { return (m_nState & GVIS_MODIFIED); }
virtual BOOL IsDropHighlighted() const { return (m_nState & GVIS_DROPHILITED); }
// Operators
public:
virtual void operator=(const CGridCellBase& cell);
// Operations
public:
virtual void Reset();
virtual BOOL Draw(CDC* pDC, int nRow, int nCol, CRect rect, BOOL bEraseBkgnd = TRUE);
virtual BOOL GetTextRect( LPRECT pRect); // i/o: i=dims of cell rect; o=dims of text rect
virtual BOOL GetTipTextRect( LPRECT pRect) { return GetTextRect( pRect); } // may override for btns, etc.
virtual CSize GetTextExtent(LPCTSTR str, CDC* pDC = NULL);
virtual CSize GetCellExtent(CDC* pDC);
// Editing
virtual BOOL Edit( int /* nRow */, int /* nCol */, CRect /* rect */, CPoint /* point */,
UINT /* nID */, UINT /* nChar */) { ASSERT( FALSE); return FALSE;}
virtual BOOL ValidateEdit(LPCTSTR str);
virtual void EndEdit() {}
// EFW - Added to print cells properly
virtual BOOL PrintCell(CDC* pDC, int nRow, int nCol, CRect rect);
// add additional protected grid members required of cells
LRESULT SendMessageToParent(int nRow, int nCol, int nMessage);
protected:
virtual void OnEndEdit();
virtual void OnMouseEnter();
virtual void OnMouseOver();
virtual void OnMouseLeave();
virtual void OnClick( CPoint PointCellRelative);
virtual void OnClickDown( CPoint PointCellRelative);
virtual void OnRClick( CPoint PointCellRelative);
virtual void OnDblClick( CPoint PointCellRelative);
virtual BOOL OnSetCursor();
protected:
DWORD m_nState; // Cell state (selected/focus etc)
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_GRIDCELLBASE_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,872 @@
/////////////////////////////////////////////////////////////////////////////
// GridCtrl.h : header file
//
// MFC Grid Control - main header
//
// Written by Chris Maunder <cmaunder@mail.com>
// Copyright (c) 1998-2002. All Rights Reserved.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.20+
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_GRIDCTRL_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_)
#define AFX_GRIDCTRL_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#include "CellRange.h"
#include "GridCell.h"
#include <afxtempl.h>
///////////////////////////////////////////////////////////////////////////////////
// Defines - these determine the features (and the final size) of the final code
///////////////////////////////////////////////////////////////////////////////////
//#define GRIDCONTROL_NO_TITLETIPS // Do not use titletips for cells with large data
//#define GRIDCONTROL_NO_DRAGDROP // Do not use OLE drag and drop
//#define GRIDCONTROL_NO_CLIPBOARD // Do not use clipboard routines
#ifdef _WIN32_WCE
# define GRIDCONTROL_NO_TITLETIPS // Do not use titletips for cells with large data
# define GRIDCONTROL_NO_DRAGDROP // Do not use OLE drag and drop
# define GRIDCONTROL_NO_CLIPBOARD // Do not use clipboard routines
# define GRIDCONTROL_NO_PRINTING // Do not use printing routines
# ifdef WCE_NO_PRINTING // Older versions of CE had different #def's
# define _WIN32_WCE_NO_PRINTING
# endif
# ifdef WCE_NO_CURSOR
# define _WIN32_WCE_NO_CURSOR
# endif
#endif // _WIN32_WCE
// Use this as the classname when inserting this control as a custom control
// in the MSVC++ dialog editor
#define GRIDCTRL_CLASSNAME _T("MFCGridCtrl") // Window class name
#define IDC_INPLACE_CONTROL 8 // ID of inplace edit controls
///////////////////////////////////////////////////////////////////////////////////
// Conditional includes
///////////////////////////////////////////////////////////////////////////////////
#ifndef GRIDCONTROL_NO_TITLETIPS
# include "TitleTip.h"
#endif
#ifndef GRIDCONTROL_NO_DRAGDROP
# include "GridDropTarget.h"
# undef GRIDCONTROL_NO_CLIPBOARD // Force clipboard functions on
#endif
#ifndef GRIDCONTROL_NO_CLIPBOARD
# include <afxole.h>
#endif
///////////////////////////////////////////////////////////////////////////////////
// Helper functions
///////////////////////////////////////////////////////////////////////////////////
// Handy functions
#define IsSHIFTpressed() ( (GetKeyState(VK_SHIFT) & (1 << (sizeof(SHORT)*8-1))) != 0 )
#define IsCTRLpressed() ( (GetKeyState(VK_CONTROL) & (1 << (sizeof(SHORT)*8-1))) != 0 )
// Backwards compatibility for pre 2.20 grid versions
#define DDX_GridControl(pDX, nIDC, rControl) DDX_Control(pDX, nIDC, rControl)
///////////////////////////////////////////////////////////////////////////////////
// Structures
///////////////////////////////////////////////////////////////////////////////////
// This structure sent to Grid's parent in a WM_NOTIFY message
typedef struct tagNM_GRIDVIEW {
NMHDR hdr;
int iRow;
int iColumn;
} NM_GRIDVIEW;
// This is sent to the Grid from child in-place edit controls
typedef struct tagGV_DISPINFO {
NMHDR hdr;
GV_ITEM item;
} GV_DISPINFO;
// This is sent to the Grid from child in-place edit controls
typedef struct tagGV_CACHEHINT {
NMHDR hdr;
CCellRange range;
} GV_CACHEHINT;
// storage typedef for each row in the grid
typedef CTypedPtrArray<CObArray, CGridCellBase*> GRID_ROW;
// For virtual mode callback
typedef BOOL (CALLBACK* GRIDCALLBACK)(GV_DISPINFO *, LPARAM);
///////////////////////////////////////////////////////////////////////////////////
// Defines
///////////////////////////////////////////////////////////////////////////////////
// Grid line/scrollbar selection
#define GVL_NONE 0L // Neither
#define GVL_HORZ 1L // Horizontal line or scrollbar
#define GVL_VERT 2L // Vertical line or scrollbar
#define GVL_BOTH 3L // Both
// Autosizing option
#define GVS_DEFAULT 0
#define GVS_HEADER 1 // Size using column fixed cells data only
#define GVS_DATA 2 // Size using column non-fixed cells data only
#define GVS_BOTH 3 // Size using column fixed and non-fixed
// Cell Searching options
#define GVNI_FOCUSED 0x0001
#define GVNI_SELECTED 0x0002
#define GVNI_DROPHILITED 0x0004
#define GVNI_READONLY 0x0008
#define GVNI_FIXED 0x0010
#define GVNI_MODIFIED 0x0020
#define GVNI_ABOVE LVNI_ABOVE
#define GVNI_BELOW LVNI_BELOW
#define GVNI_TOLEFT LVNI_TOLEFT
#define GVNI_TORIGHT LVNI_TORIGHT
#define GVNI_ALL (LVNI_BELOW|LVNI_TORIGHT|LVNI_TOLEFT)
#define GVNI_AREA (LVNI_BELOW|LVNI_TORIGHT)
// Hit test values (not yet implemented)
#define GVHT_DATA 0x0000
#define GVHT_TOPLEFT 0x0001
#define GVHT_COLHDR 0x0002
#define GVHT_ROWHDR 0x0004
#define GVHT_COLSIZER 0x0008
#define GVHT_ROWSIZER 0x0010
#define GVHT_LEFT 0x0020
#define GVHT_RIGHT 0x0040
#define GVHT_ABOVE 0x0080
#define GVHT_BELOW 0x0100
// Messages sent to the grid's parent (More will be added in future)
#define GVN_BEGINDRAG LVN_BEGINDRAG // LVN_FIRST-9
#define GVN_BEGINLABELEDIT LVN_BEGINLABELEDIT // LVN_FIRST-5
#define GVN_BEGINRDRAG LVN_BEGINRDRAG
#define GVN_COLUMNCLICK LVN_COLUMNCLICK
#define GVN_DELETEITEM LVN_DELETEITEM
#define GVN_ENDLABELEDIT LVN_ENDLABELEDIT // LVN_FIRST-6
#define GVN_SELCHANGING LVN_ITEMCHANGING
#define GVN_SELCHANGED LVN_ITEMCHANGED
#define GVN_GETDISPINFO LVN_GETDISPINFO
#define GVN_ODCACHEHINT LVN_ODCACHEHINT
class CGridCtrl;
/////////////////////////////////////////////////////////////////////////////
// CGridCtrl window
class AFX_EXT_CLASS CGridCtrl : public CWnd
{
DECLARE_DYNCREATE(CGridCtrl)
friend class CGridCell;
friend class CGridCellBase;
// Construction
public:
CGridCtrl(int nRows = 0, int nCols = 0, int nFixedRows = 0, int nFixedCols = 0);
BOOL Create(const RECT& rect, CWnd* parent, UINT nID,
DWORD dwStyle = WS_CHILD | WS_BORDER | WS_TABSTOP | WS_VISIBLE);
///////////////////////////////////////////////////////////////////////////////////
// Attributes
///////////////////////////////////////////////////////////////////////////////////
public:
int GetRowCount() const { return m_nRows; }
int GetColumnCount() const { return m_nCols; }
int GetFixedRowCount() const { return m_nFixedRows; }
int GetFixedColumnCount() const { return m_nFixedCols; }
BOOL SetRowCount(int nRows = 10);
BOOL SetColumnCount(int nCols = 10);
BOOL SetFixedRowCount(int nFixedRows = 1);
BOOL SetFixedColumnCount(int nFixedCols = 1);
int GetRowHeight(int nRow) const;
BOOL SetRowHeight(int row, int height);
int GetColumnWidth(int nCol) const;
BOOL SetColumnWidth(int col, int width);
BOOL GetCellOrigin(int nRow, int nCol, LPPOINT p);
BOOL GetCellOrigin(const CCellID& cell, LPPOINT p);
BOOL GetCellRect(int nRow, int nCol, LPRECT pRect);
BOOL GetCellRect(const CCellID& cell, LPRECT pRect);
BOOL GetTextRect(const CCellID& cell, LPRECT pRect);
BOOL GetTextRect(int nRow, int nCol, LPRECT pRect);
CCellID GetCellFromPt(CPoint point, BOOL bAllowFixedCellCheck = TRUE);
int GetFixedRowHeight() const;
int GetFixedColumnWidth() const;
long GetVirtualWidth() const;
long GetVirtualHeight() const;
CSize GetTextExtent(int nRow, int nCol, LPCTSTR str);
// EFW - Get extent of current text in cell
inline CSize GetCellTextExtent(int nRow, int nCol) { return GetTextExtent(nRow, nCol, GetItemText(nRow,nCol)); }
void SetGridBkColor(COLORREF clr) { m_crGridBkColour = clr; }
COLORREF GetGridBkColor() const { return m_crGridBkColour; }
void SetGridLineColor(COLORREF clr) { m_crGridLineColour = clr; }
COLORREF GetGridLineColor() const { return m_crGridLineColour; }
void SetTitleTipBackClr(COLORREF clr = CLR_DEFAULT) { m_crTTipBackClr = clr; }
COLORREF GetTitleTipBackClr() { return m_crTTipBackClr; }
void SetTitleTipTextClr(COLORREF clr = CLR_DEFAULT) { m_crTTipTextClr = clr; }
COLORREF GetTitleTipTextClr() { return m_crTTipTextClr; }
// ***************************************************************************** //
// These have been deprecated. Use GetDefaultCell and then set the colors
void SetTextColor(COLORREF clr) { m_cellDefault.SetTextClr(clr); }
COLORREF GetTextColor() { return m_cellDefault.GetTextClr(); }
void SetTextBkColor(COLORREF clr) { m_cellDefault.SetBackClr(clr); }
COLORREF GetTextBkColor() { return m_cellDefault.GetBackClr(); }
void SetFixedTextColor(COLORREF clr) { m_cellFixedRowDef.SetTextClr(clr);
m_cellFixedColDef.SetTextClr(clr);
m_cellFixedRowColDef.SetTextClr(clr); }
COLORREF GetFixedTextColor() const { return m_cellFixedRowDef.GetTextClr(); }
void SetFixedBkColor(COLORREF clr) { m_cellFixedRowDef.SetBackClr(clr);
m_cellFixedColDef.SetBackClr(clr);
m_cellFixedRowColDef.SetBackClr(clr); }
COLORREF GetFixedBkColor() const { return m_cellFixedRowDef.GetBackClr(); }
void SetGridColor(COLORREF clr) { SetGridLineColor(clr); }
COLORREF GetGridColor() { return GetGridLineColor(); }
void SetBkColor(COLORREF clr) { SetGridBkColor(clr); }
COLORREF GetBkColor() { return GetGridBkColor(); }
void SetDefCellMargin( int nMargin) { m_cellDefault.SetMargin(nMargin);
m_cellFixedRowDef.SetMargin(nMargin);
m_cellFixedColDef.SetMargin(nMargin);
m_cellFixedRowColDef.SetMargin(nMargin); }
int GetDefCellMargin() const { return m_cellDefault.GetMargin(); }
int GetDefCellHeight() const { return m_cellDefault.GetHeight(); }
void SetDefCellHeight(int nHeight) { m_cellDefault.SetHeight(nHeight);
m_cellFixedRowDef.SetHeight(nHeight);
m_cellFixedColDef.SetHeight(nHeight);
m_cellFixedRowColDef.SetHeight(nHeight); }
int GetDefCellWidth() const { return m_cellDefault.GetWidth(); }
void SetDefCellWidth(int nWidth) { m_cellDefault.SetWidth(nWidth);
m_cellFixedRowDef.SetWidth(nWidth);
m_cellFixedColDef.SetWidth(nWidth);
m_cellFixedRowColDef.SetWidth(nWidth); }
// ***************************************************************************** //
int GetSelectedCount() const { return (int)m_SelectedCellMap.GetCount(); }
CCellID SetFocusCell(CCellID cell);
CCellID SetFocusCell(int nRow, int nCol);
CCellID GetFocusCell() const { return m_idCurrentCell; }
void SetVirtualMode(BOOL bVirtual);
BOOL GetVirtualMode() const { return m_bVirtualMode; }
void SetCallbackFunc(GRIDCALLBACK pCallback,
LPARAM lParam) { m_pfnCallback = pCallback; m_lParam = lParam; }
GRIDCALLBACK GetCallbackFunc() { return m_pfnCallback; }
void SetImageList(CImageList* pList) { m_pImageList = pList; }
CImageList* GetImageList() const { return m_pImageList; }
void SetGridLines(int nWhichLines = GVL_BOTH);
int GetGridLines() const { return m_nGridLines; }
void SetEditable(BOOL bEditable = TRUE) { m_bEditable = bEditable; }
BOOL IsEditable() const { return m_bEditable; }
void SetListMode(BOOL bEnableListMode = TRUE);
BOOL GetListMode() const { return m_bListMode; }
void SetSingleRowSelection(BOOL bSing = TRUE) { m_bSingleRowSelection = bSing; }
BOOL GetSingleRowSelection() { return m_bSingleRowSelection & m_bListMode; }
void SetSingleColSelection(BOOL bSing = TRUE) { m_bSingleColSelection = bSing; }
BOOL GetSingleColSelection() { return m_bSingleColSelection; }
void EnableSelection(BOOL bEnable = TRUE) { ResetSelectedRange(); m_bEnableSelection = bEnable; ResetSelectedRange(); }
BOOL IsSelectable() const { return m_bEnableSelection; }
void SetFixedColumnSelection(BOOL bSelect) { m_bFixedColumnSelection = bSelect;}
BOOL GetFixedColumnSelection() { return m_bFixedColumnSelection; }
void SetFixedRowSelection(BOOL bSelect) { m_bFixedRowSelection = bSelect; }
BOOL GetFixedRowSelection() { return m_bFixedRowSelection; }
void EnableDragAndDrop(BOOL bAllow = TRUE) { m_bAllowDragAndDrop = bAllow; }
BOOL GetDragAndDrop() const { return m_bAllowDragAndDrop; }
void SetRowResize(BOOL bResize = TRUE) { m_bAllowRowResize = bResize; }
BOOL GetRowResize() const { return m_bAllowRowResize; }
void SetColumnResize(BOOL bResize = TRUE) { m_bAllowColumnResize = bResize; }
BOOL GetColumnResize() const { return m_bAllowColumnResize; }
void SetHeaderSort(BOOL bSortOnClick = TRUE) { m_bSortOnClick = bSortOnClick; }
BOOL GetHeaderSort() const { return m_bSortOnClick; }
void SetHandleTabKey(BOOL bHandleTab = TRUE) { m_bHandleTabKey = bHandleTab; }
BOOL GetHandleTabKey() const { return m_bHandleTabKey; }
void SetDoubleBuffering(BOOL bBuffer = TRUE) { m_bDoubleBuffer = bBuffer; }
BOOL GetDoubleBuffering() const { return m_bDoubleBuffer; }
void EnableTitleTips(BOOL bEnable = TRUE) { m_bTitleTips = bEnable; }
BOOL GetTitleTips() { return m_bTitleTips; }
void SetSortColumn(int nCol);
int GetSortColumn() const { return m_nSortColumn; }
void SetSortAscending(BOOL bAscending) { m_bAscending = bAscending; }
BOOL GetSortAscending() const { return m_bAscending; }
void SetTrackFocusCell(BOOL bTrack) { m_bTrackFocusCell = bTrack; }
BOOL GetTrackFocusCell() { return m_bTrackFocusCell; }
void SetFrameFocusCell(BOOL bFrame) { m_bFrameFocus = bFrame; }
BOOL GetFrameFocusCell() { return m_bFrameFocus; }
void SetAutoSizeStyle(int nStyle = GVS_BOTH) { m_nAutoSizeColumnStyle = nStyle; }
int GetAutoSizeStyle() { return m_nAutoSizeColumnStyle; }
void EnableHiddenColUnhide(BOOL bEnable = TRUE){ m_bHiddenColUnhide = bEnable; }
BOOL GetHiddenColUnhide() { return m_bHiddenColUnhide; }
void EnableHiddenRowUnhide(BOOL bEnable = TRUE){ m_bHiddenRowUnhide = bEnable; }
BOOL GetHiddenRowUnhide() { return m_bHiddenRowUnhide; }
void EnableColumnHide(BOOL bEnable = TRUE) { m_bAllowColHide = bEnable; }
BOOL GetColumnHide() { return m_bAllowColHide; }
void EnableRowHide(BOOL bEnable = TRUE) { m_bAllowRowHide = bEnable; }
BOOL GetRowHide() { return m_bAllowRowHide; }
///////////////////////////////////////////////////////////////////////////////////
// default Grid cells. Use these for setting default values such as colors and fonts
///////////////////////////////////////////////////////////////////////////////////
public:
CGridCellBase* GetDefaultCell(BOOL bFixedRow, BOOL bFixedCol) const;
///////////////////////////////////////////////////////////////////////////////////
// Grid cell Attributes
///////////////////////////////////////////////////////////////////////////////////
public:
CGridCellBase* GetCell(int nRow, int nCol) const; // Get the actual cell!
void SetModified(BOOL bModified = TRUE, int nRow = -1, int nCol = -1);
BOOL GetModified(int nRow = -1, int nCol = -1);
BOOL IsCellFixed(int nRow, int nCol);
BOOL SetItem(const GV_ITEM* pItem);
BOOL GetItem(GV_ITEM* pItem);
BOOL SetItemText(int nRow, int nCol, LPCTSTR str);
// The following was virtual. If you want to override, use
// CGridCellBase-derived class's GetText() to accomplish same thing
CString GetItemText(int nRow, int nCol) const;
// EFW - 06/13/99 - Added to support printf-style formatting codes.
// Also supports use with a string resource ID
#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 210)
BOOL SetItemTextFmt(int nRow, int nCol, LPCTSTR szFmt, ...);
BOOL SetItemTextFmtID(int nRow, int nCol, UINT nID, ...);
#endif
BOOL SetItemData(int nRow, int nCol, LPARAM lParam);
LPARAM GetItemData(int nRow, int nCol) const;
BOOL SetItemImage(int nRow, int nCol, int iImage);
int GetItemImage(int nRow, int nCol) const;
BOOL SetItemState(int nRow, int nCol, UINT state);
UINT GetItemState(int nRow, int nCol) const;
BOOL SetItemFormat(int nRow, int nCol, UINT nFormat);
UINT GetItemFormat(int nRow, int nCol) const;
BOOL SetItemBkColour(int nRow, int nCol, COLORREF cr = CLR_DEFAULT);
COLORREF GetItemBkColour(int nRow, int nCol) const;
BOOL SetItemFgColour(int nRow, int nCol, COLORREF cr = CLR_DEFAULT);
COLORREF GetItemFgColour(int nRow, int nCol) const;
BOOL SetItemFont(int nRow, int nCol, const LOGFONT* lf);
const LOGFONT* GetItemFont(int nRow, int nCol);
BOOL IsItemEditing(int nRow, int nCol);
BOOL SetCellType(int nRow, int nCol, CRuntimeClass* pRuntimeClass);
BOOL SetDefaultCellType( CRuntimeClass* pRuntimeClass);
///////////////////////////////////////////////////////////////////////////////////
// Operations
///////////////////////////////////////////////////////////////////////////////////
public:
int InsertColumn(LPCTSTR strHeading, UINT nFormat = DT_CENTER|DT_VCENTER|DT_SINGLELINE,
int nColumn = -1);
int InsertRow(LPCTSTR strHeading, int nRow = -1);
BOOL DeleteColumn(int nColumn);
BOOL DeleteRow(int nRow);
BOOL DeleteNonFixedRows();
BOOL DeleteAllItems();
void ClearCells(CCellRange Selection);
BOOL AutoSizeRow(int nRow, BOOL bResetScroll = TRUE);
BOOL AutoSizeColumn(int nCol, UINT nAutoSizeStyle = GVS_DEFAULT, BOOL bResetScroll = TRUE);
void AutoSizeRows();
void AutoSizeColumns(UINT nAutoSizeStyle = GVS_DEFAULT);
void AutoSize(UINT nAutoSizeStyle = GVS_DEFAULT);
void ExpandColumnsToFit(BOOL bExpandFixed = TRUE);
void ExpandLastColumn();
void ExpandRowsToFit(BOOL bExpandFixed = TRUE);
void ExpandToFit(BOOL bExpandFixed = TRUE);
void Refresh();
void AutoFill(); // Fill grid with blank cells
void EnsureVisible(CCellID &cell) { EnsureVisible(cell.row, cell.col); }
void EnsureVisible(int nRow, int nCol);
BOOL IsCellVisible(int nRow, int nCol);
BOOL IsCellVisible(CCellID cell);
BOOL IsCellEditable(int nRow, int nCol) const;
BOOL IsCellEditable(CCellID &cell) const;
BOOL IsCellSelected(int nRow, int nCol) const;
BOOL IsCellSelected(CCellID &cell) const;
// SetRedraw stops/starts redraws on things like changing the # rows/columns
// and autosizing, but not for user-intervention such as resizes
void SetRedraw(BOOL bAllowDraw, BOOL bResetScrollBars = FALSE);
BOOL RedrawCell(int nRow, int nCol, CDC* pDC = NULL);
BOOL RedrawCell(const CCellID& cell, CDC* pDC = NULL);
BOOL RedrawRow(int row);
BOOL RedrawColumn(int col);
#ifndef _WIN32_WCE
BOOL Save(LPCTSTR filename, TCHAR chSeparator = _T(','));
BOOL Load(LPCTSTR filename, TCHAR chSeparator = _T(','));
#endif
///////////////////////////////////////////////////////////////////////////////////
// Cell Ranges
///////////////////////////////////////////////////////////////////////////////////
public:
CCellRange GetCellRange() const;
CCellRange GetSelectedCellRange() const;
void SetSelectedRange(const CCellRange& Range, BOOL bForceRepaint = FALSE, BOOL bSelectCells = TRUE);
void SetSelectedRange(int nMinRow, int nMinCol, int nMaxRow, int nMaxCol,
BOOL bForceRepaint = FALSE, BOOL bSelectCells = TRUE);
BOOL IsValid(int nRow, int nCol) const;
BOOL IsValid(const CCellID& cell) const;
BOOL IsValid(const CCellRange& range) const;
///////////////////////////////////////////////////////////////////////////////////
// Clipboard, drag and drop, and cut n' paste operations
///////////////////////////////////////////////////////////////////////////////////
#ifndef GRIDCONTROL_NO_CLIPBOARD
virtual void CutSelectedText();
virtual COleDataSource* CopyTextFromGrid();
virtual BOOL PasteTextToGrid(CCellID cell, COleDataObject* pDataObject, BOOL bSelectPastedCells=TRUE);
#endif
#ifndef GRIDCONTROL_NO_DRAGDROP
public:
virtual void OnBeginDrag();
virtual DROPEFFECT OnDragEnter(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point);
virtual DROPEFFECT OnDragOver(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point);
virtual void OnDragLeave();
virtual BOOL OnDrop(COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point);
#endif
#ifndef GRIDCONTROL_NO_CLIPBOARD
virtual void OnEditCut();
virtual void OnEditCopy();
virtual void OnEditPaste();
#endif
virtual void OnEditSelectAll();
///////////////////////////////////////////////////////////////////////////////////
// Misc.
///////////////////////////////////////////////////////////////////////////////////
public:
CCellID GetNextItem(CCellID& cell, int nFlags) const;
BOOL SortItems(int nCol, BOOL bAscending, LPARAM data = 0);
BOOL SortTextItems(int nCol, BOOL bAscending, LPARAM data = 0);
BOOL SortItems(PFNLVCOMPARE pfnCompare, int nCol, BOOL bAscending, LPARAM data = 0);
void SetCompareFunction(PFNLVCOMPARE pfnCompare);
// in-built sort functions
static int CALLBACK pfnCellTextCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
static int CALLBACK pfnCellNumericCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
///////////////////////////////////////////////////////////////////////////////////
// Printing
///////////////////////////////////////////////////////////////////////////////////
#if !defined(_WIN32_WCE_NO_PRINTING) && !defined(GRIDCONTROL_NO_PRINTING)
public:
void Print(CPrintDialog* pPrntDialog = NULL);
// EFW - New printing support functions
void EnableWysiwygPrinting(BOOL bEnable = TRUE) { m_bWysiwygPrinting = bEnable; }
BOOL GetWysiwygPrinting() { return m_bWysiwygPrinting; }
void SetShadedPrintOut(BOOL bEnable = TRUE) { m_bShadedPrintOut = bEnable; }
BOOL GetShadedPrintOut(void) { return m_bShadedPrintOut; }
// Use -1 to have it keep the existing value
void SetPrintMarginInfo(int nHeaderHeight, int nFooterHeight,
int nLeftMargin, int nRightMargin, int nTopMargin,
int nBottomMargin, int nGap);
void GetPrintMarginInfo(int &nHeaderHeight, int &nFooterHeight,
int &nLeftMargin, int &nRightMargin, int &nTopMargin,
int &nBottomMargin, int &nGap);
///////////////////////////////////////////////////////////////////////////////////
// Printing overrides for derived classes
///////////////////////////////////////////////////////////////////////////////////
public:
virtual void OnBeginPrinting(CDC *pDC, CPrintInfo *pInfo);
virtual void OnPrint(CDC *pDC, CPrintInfo *pInfo);
virtual void OnEndPrinting(CDC *pDC, CPrintInfo *pInfo);
#endif // #if !defined(_WIN32_WCE_NO_PRINTING) && !defined(GRIDCONTROL_NO_PRINTING)
// Implementation
public:
virtual ~CGridCtrl();
protected:
BOOL RegisterWindowClass();
BOOL Initialise();
void SetupDefaultCells();
LRESULT SendMessageToParent(int nRow, int nCol, int nMessage) const;
LRESULT SendDisplayRequestToParent(GV_DISPINFO* pDisplayInfo) const;
LRESULT SendCacheHintToParent(const CCellRange& range) const;
BOOL InvalidateCellRect(const int row, const int col);
BOOL InvalidateCellRect(const CCellID& cell);
BOOL InvalidateCellRect(const CCellRange& cellRange);
void EraseBkgnd(CDC* pDC);
BOOL GetCellRangeRect(const CCellRange& cellRange, LPRECT lpRect);
BOOL SetCell(int nRow, int nCol, CGridCellBase* pCell);
int SetMouseMode(int nMode) { int nOldMode = m_MouseMode; m_MouseMode = nMode; return nOldMode; }
int GetMouseMode() const { return m_MouseMode; }
BOOL MouseOverRowResizeArea(CPoint& point);
BOOL MouseOverColumnResizeArea(CPoint& point);
CCellID GetTopleftNonFixedCell(BOOL bForceRecalculation = FALSE);
CCellRange GetUnobstructedNonFixedCellRange(BOOL bForceRecalculation = FALSE);
CCellRange GetVisibleNonFixedCellRange(LPRECT pRect = NULL, BOOL bForceRecalculation = FALSE);
BOOL IsVisibleVScroll() { return ( (m_nBarState & GVL_VERT) > 0); }
BOOL IsVisibleHScroll() { return ( (m_nBarState & GVL_HORZ) > 0); }
void ResetSelectedRange();
void ResetScrollBars();
void EnableScrollBars(int nBar, BOOL bEnable = TRUE);
int GetScrollPos32(int nBar, BOOL bGetTrackPos = FALSE);
BOOL SetScrollPos32(int nBar, int nPos, BOOL bRedraw = TRUE);
BOOL SortTextItems(int nCol, BOOL bAscending, int low, int high);
BOOL SortItems(PFNLVCOMPARE pfnCompare, int nCol, BOOL bAscending, LPARAM data,
int low, int high);
CPoint GetPointClicked(int nRow, int nCol, const CPoint& point);
void ValidateAndModifyCellContents(int nRow, int nCol, LPCTSTR strText);
// Overrrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CGridCtrl)
protected:
virtual void PreSubclassWindow();
//}}AFX_VIRTUAL
protected:
#if !defined(_WIN32_WCE_NO_PRINTING) && !defined(GRIDCONTROL_NO_PRINTING)
// Printing
virtual void PrintFixedRowCells(int nStartColumn, int nStopColumn, int& row, CRect& rect,
CDC *pDC, BOOL& bFirst);
virtual void PrintColumnHeadings(CDC *pDC, CPrintInfo *pInfo);
virtual void PrintHeader(CDC *pDC, CPrintInfo *pInfo);
virtual void PrintFooter(CDC *pDC, CPrintInfo *pInfo);
virtual void PrintRowButtons(CDC *pDC, CPrintInfo* /*pInfo*/);
#endif
#ifndef GRIDCONTROL_NO_DRAGDROP
// Drag n' drop
virtual CImageList* CreateDragImage(CPoint *pHotSpot); // no longer necessary
#endif
// Mouse Clicks
virtual void OnFixedColumnClick(CCellID& cell);
virtual void OnFixedRowClick(CCellID& cell);
// Editing
virtual void OnEditCell(int nRow, int nCol, CPoint point, UINT nChar);
virtual void OnEndEditCell(int nRow, int nCol, CString str);
virtual BOOL ValidateEdit(int nRow, int nCol, LPCTSTR str);
virtual void EndEditing();
// Drawing
virtual void OnDraw(CDC* pDC);
// CGridCellBase Creation and Cleanup
virtual CGridCellBase* CreateCell(int nRow, int nCol);
virtual void DestroyCell(int nRow, int nCol);
// Attributes
protected:
// General attributes
COLORREF m_crFixedTextColour, m_crFixedBkColour;
COLORREF m_crGridBkColour, m_crGridLineColour;
COLORREF m_crWindowText, m_crWindowColour, m_cr3DFace, // System colours
m_crShadow;
COLORREF m_crTTipBackClr, m_crTTipTextClr; // Titletip colours - FNA
BOOL m_bVirtualMode;
LPARAM m_lParam; // lParam for callback
GRIDCALLBACK m_pfnCallback; // The callback function
int m_nGridLines;
BOOL m_bEditable;
BOOL m_bModified;
BOOL m_bAllowDragAndDrop;
BOOL m_bListMode;
BOOL m_bSingleRowSelection;
BOOL m_bSingleColSelection;
BOOL m_bAllowDraw;
BOOL m_bEnableSelection;
BOOL m_bFixedRowSelection, m_bFixedColumnSelection;
BOOL m_bSortOnClick;
BOOL m_bHandleTabKey;
BOOL m_bDoubleBuffer;
BOOL m_bTitleTips;
int m_nBarState;
BOOL m_bWysiwygPrinting;
BOOL m_bHiddenColUnhide, m_bHiddenRowUnhide;
BOOL m_bAllowColHide, m_bAllowRowHide;
BOOL m_bAutoSizeSkipColHdr;
BOOL m_bTrackFocusCell;
BOOL m_bFrameFocus;
UINT m_nAutoSizeColumnStyle;
// Cell size details
int m_nRows, m_nFixedRows, m_nCols, m_nFixedCols;
CUIntArray m_arRowHeights, m_arColWidths;
int m_nVScrollMax, m_nHScrollMax;
// Fonts and images
CRuntimeClass* m_pRtcDefault; // determines kind of Grid Cell created by default
CGridDefaultCell m_cellDefault; // "default" cell. Contains default colours, font etc.
CGridDefaultCell m_cellFixedColDef, m_cellFixedRowDef, m_cellFixedRowColDef;
CFont m_PrinterFont; // for the printer
CImageList* m_pImageList;
// Cell data
CTypedPtrArray<CObArray, GRID_ROW*> m_RowData;
// Mouse operations such as cell selection
int m_MouseMode;
BOOL m_bLMouseButtonDown, m_bRMouseButtonDown;
CPoint m_LeftClickDownPoint, m_LastMousePoint;
CCellID m_LeftClickDownCell, m_SelectionStartCell;
CCellID m_idCurrentCell, m_idTopLeftCell;
int m_nTimerID;
int m_nTimerInterval;
int m_nResizeCaptureRange;
BOOL m_bAllowRowResize, m_bAllowColumnResize;
int m_nRowsPerWheelNotch;
CMap<DWORD,DWORD, CCellID, CCellID&> m_SelectedCellMap, m_PrevSelectedCellMap;
#ifndef GRIDCONTROL_NO_TITLETIPS
CTitleTip m_TitleTip; // Title tips for cells
#endif
// Drag and drop
CCellID m_LastDragOverCell;
#ifndef GRIDCONTROL_NO_DRAGDROP
CGridDropTarget m_DropTarget; // OLE Drop target for the grid
#endif
// Printing information
CSize m_CharSize;
int m_nPageHeight;
CSize m_LogicalPageSize, // Page size in gridctrl units.
m_PaperSize; // Page size in device units.
// additional properties to support Wysiwyg printing
int m_nPageWidth;
int m_nPrintColumn;
int m_nCurrPrintRow;
int m_nNumPages;
int m_nPageMultiplier;
// sorting
int m_bAscending;
int m_nSortColumn;
PFNLVCOMPARE m_pfnCompare;
// EFW - Added to support shaded/unshaded printout. If true, colored
// cells will print as-is. If false, all text prints as black on white.
BOOL m_bShadedPrintOut;
// EFW - Added support for user-definable margins. Top and bottom are in
// lines. Left, right, and gap are in characters (avg width is used).
int m_nHeaderHeight, m_nFooterHeight, m_nLeftMargin,
m_nRightMargin, m_nTopMargin, m_nBottomMargin, m_nGap;
protected:
void SelectAllCells();
void SelectColumns(CCellID currentCell, BOOL bForceRedraw=FALSE, BOOL bSelectCells=TRUE);
void SelectRows(CCellID currentCell, BOOL bForceRedraw=FALSE, BOOL bSelectCells=TRUE);
void SelectCells(CCellID currentCell, BOOL bForceRedraw=FALSE, BOOL bSelectCells=TRUE);
void OnSelecting(const CCellID& currentCell);
// Generated message map functions
//{{AFX_MSG(CGridCtrl)
afx_msg void OnPaint();
afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnTimer(UINT nIDEvent);
afx_msg UINT OnGetDlgCode();
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg void OnUpdateEditSelectAll(CCmdUI* pCmdUI);
//}}AFX_MSG
#ifndef _WIN32_WCE_NO_CURSOR
afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
#endif
#ifndef _WIN32_WCE
afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
afx_msg void OnRButtonUp(UINT nFlags, CPoint point); // EFW - Added
afx_msg void OnSysColorChange();
#endif
#ifndef _WIN32_WCE_NO_CURSOR
afx_msg void OnCaptureChanged(CWnd *pWnd);
#endif
#ifndef GRIDCONTROL_NO_CLIPBOARD
afx_msg void OnUpdateEditCopy(CCmdUI* pCmdUI);
afx_msg void OnUpdateEditCut(CCmdUI* pCmdUI);
afx_msg void OnUpdateEditPaste(CCmdUI* pCmdUI);
#endif
#if (_MFC_VER >= 0x0421) || (_WIN32_WCE >= 210)
afx_msg void OnSettingChange(UINT uFlags, LPCTSTR lpszSection);
#endif
#if !defined(_WIN32_WCE) && (_MFC_VER >= 0x0421)
afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
#endif
afx_msg LRESULT OnSetFont(WPARAM hFont, LPARAM lParam);
afx_msg LRESULT OnGetFont(WPARAM hFont, LPARAM lParam);
afx_msg LRESULT OnImeChar(WPARAM wCharCode, LPARAM lParam);
afx_msg void OnEndInPlaceEdit(NMHDR* pNMHDR, LRESULT* pResult);
DECLARE_MESSAGE_MAP()
enum eMouseModes { MOUSE_NOTHING, MOUSE_SELECT_ALL, MOUSE_SELECT_COL, MOUSE_SELECT_ROW,
MOUSE_SELECT_CELLS, MOUSE_SCROLLING_CELLS,
MOUSE_OVER_ROW_DIVIDE, MOUSE_SIZING_ROW,
MOUSE_OVER_COL_DIVIDE, MOUSE_SIZING_COL,
MOUSE_PREPARE_EDIT,
#ifndef GRIDCONTROL_NO_DRAGDROP
MOUSE_PREPARE_DRAG, MOUSE_DRAGGING
#endif
};
};
// Returns the default cell implementation for the given grid region
inline CGridCellBase* CGridCtrl::GetDefaultCell(BOOL bFixedRow, BOOL bFixedCol) const
{
if (bFixedRow && bFixedCol) return (CGridCellBase*) &m_cellFixedRowColDef;
if (bFixedRow) return (CGridCellBase*) &m_cellFixedRowDef;
if (bFixedCol) return (CGridCellBase*) &m_cellFixedColDef;
return (CGridCellBase*) &m_cellDefault;
}
inline CGridCellBase* CGridCtrl::GetCell(int nRow, int nCol) const
{
if (nRow < 0 || nRow >= m_nRows || nCol < 0 || nCol >= m_nCols)
return NULL;
if (GetVirtualMode())
{
CGridCellBase* pCell = GetDefaultCell(nRow < m_nFixedRows, nCol < m_nFixedCols);
static GV_DISPINFO gvdi;
gvdi.item.row = nRow;
gvdi.item.col = nCol;
gvdi.item.mask = 0xFFFFFFFF;
gvdi.item.nState = 0;
gvdi.item.nFormat = pCell->GetFormat();
gvdi.item.iImage = pCell->GetImage();
gvdi.item.crBkClr = pCell->GetBackClr();
gvdi.item.crFgClr = pCell->GetTextClr();
gvdi.item.lParam = pCell->GetData();
memcpy(&gvdi.item.lfFont, pCell->GetFont(), sizeof(LOGFONT));
gvdi.item.nMargin = pCell->GetMargin();
gvdi.item.strText.Empty();
// Fix the state bits
if (IsCellSelected(nRow, nCol)) gvdi.item.nState |= GVIS_SELECTED;
if (nRow < GetFixedRowCount()) gvdi.item.nState |= (GVIS_FIXED | GVIS_FIXEDROW);
if (nCol < GetFixedColumnCount()) gvdi.item.nState |= (GVIS_FIXED | GVIS_FIXEDCOL);
if (GetFocusCell() == CCellID(nRow, nCol)) gvdi.item.nState |= GVIS_FOCUSED;
if (m_pfnCallback)
m_pfnCallback(&gvdi, m_lParam);
else
SendDisplayRequestToParent(&gvdi);
static CGridCell cell;
cell.SetState(gvdi.item.nState);
cell.SetFormat(gvdi.item.nFormat);
cell.SetImage(gvdi.item.iImage);
cell.SetBackClr(gvdi.item.crBkClr);
cell.SetTextClr(gvdi.item.crFgClr);
cell.SetData(gvdi.item.lParam);
cell.SetFont(&(gvdi.item.lfFont));
cell.SetMargin(gvdi.item.nMargin);
cell.SetText(gvdi.item.strText);
cell.SetGrid((CGridCtrl*)this);
return (CGridCellBase*) &cell;
}
GRID_ROW* pRow = m_RowData[nRow];
if (!pRow) return NULL;
return pRow->GetAt(nCol);
}
inline BOOL CGridCtrl::SetCell(int nRow, int nCol, CGridCellBase* pCell)
{
if (GetVirtualMode())
return FALSE;
if (nRow < 0 || nRow >= m_nRows || nCol < 0 || nCol >= m_nCols)
return FALSE;
GRID_ROW* pRow = m_RowData[nRow];
if (!pRow) return FALSE;
pCell->SetCoords( nRow, nCol);
pRow->SetAt(nCol, pCell);
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_GRIDCTRL_H__519FA702_722C_11D1_ABBA_00A0243D1382__INCLUDED_)

View File

@@ -0,0 +1,156 @@
// GridDropTarget.cpp : implementation file
//
// MFC Grid Control - Drag/Drop target implementation
//
// CGridDropTarget is an OLE drop target for CGridCtrl. All it does
// is handle the drag and drop windows messages and pass them
// directly onto the grid control.
//
// Written by Chris Maunder <cmaunder@mail.com>
// Copyright (c) 1998-2002. All Rights Reserved.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.10+
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "GridCtrl.h"
#ifndef GRIDCONTROL_NO_DRAGDROP
#include "GridDropTarget.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CGridDropTarget
CGridDropTarget::CGridDropTarget()
{
m_pGridCtrl = NULL;
m_bRegistered = FALSE;
}
CGridDropTarget::~CGridDropTarget()
{
}
// Overloaded Register() function performs the normal COleDropTarget::Register
// but also serves to connect this COleDropTarget with the parent grid control,
// where all drop messages will ultimately be forwarded.
BOOL CGridDropTarget::Register(CGridCtrl *pGridCtrl)
{
if (m_bRegistered)
return FALSE;
// Stop re-entry problems
static BOOL bInProcedure = FALSE;
if (bInProcedure)
return FALSE;
bInProcedure = TRUE;
ASSERT(pGridCtrl->IsKindOf(RUNTIME_CLASS(CGridCtrl)));
ASSERT(pGridCtrl);
if (!pGridCtrl || !pGridCtrl->IsKindOf(RUNTIME_CLASS(CGridCtrl)))
{
bInProcedure = FALSE;
return FALSE;
}
m_pGridCtrl = pGridCtrl;
m_bRegistered = COleDropTarget::Register(pGridCtrl);
bInProcedure = FALSE;
return m_bRegistered;
}
void CGridDropTarget::Revoke()
{
m_bRegistered = FALSE;
COleDropTarget::Revoke();
}
BEGIN_MESSAGE_MAP(CGridDropTarget, COleDropTarget)
//{{AFX_MSG_MAP(CGridDropTarget)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CGridDropTarget message handlers
DROPEFFECT CGridDropTarget::OnDragScroll(CWnd* pWnd, DWORD dwKeyState, CPoint /*point*/)
{
// TRACE("In CGridDropTarget::OnDragScroll\n");
if (pWnd->GetSafeHwnd() == m_pGridCtrl->GetSafeHwnd())
{
if (dwKeyState & MK_CONTROL)
return DROPEFFECT_COPY;
else
return DROPEFFECT_MOVE;
} else
return DROPEFFECT_NONE;
}
DROPEFFECT CGridDropTarget::OnDragEnter(CWnd* pWnd, COleDataObject* pDataObject,
DWORD dwKeyState, CPoint point)
{
TRACE(_T("In CGridDropTarget::OnDragEnter\n"));
ASSERT(m_pGridCtrl);
if (pWnd->GetSafeHwnd() == m_pGridCtrl->GetSafeHwnd())
return m_pGridCtrl->OnDragEnter(pDataObject, dwKeyState, point);
else
return DROPEFFECT_NONE;
}
void CGridDropTarget::OnDragLeave(CWnd* pWnd)
{
TRACE(_T("In CGridDropTarget::OnDragLeave\n"));
ASSERT(m_pGridCtrl);
if (pWnd->GetSafeHwnd() == m_pGridCtrl->GetSafeHwnd())
m_pGridCtrl->OnDragLeave();
}
DROPEFFECT CGridDropTarget::OnDragOver(CWnd* pWnd, COleDataObject* pDataObject,
DWORD dwKeyState, CPoint point)
{
// TRACE("In CGridDropTarget::OnDragOver\n");
ASSERT(m_pGridCtrl);
if (pWnd->GetSafeHwnd() == m_pGridCtrl->GetSafeHwnd())
return m_pGridCtrl->OnDragOver(pDataObject, dwKeyState, point);
else
return DROPEFFECT_NONE;
}
BOOL CGridDropTarget::OnDrop(CWnd* pWnd, COleDataObject* pDataObject,
DROPEFFECT dropEffect, CPoint point)
{
TRACE(_T("In CGridDropTarget::OnDrop\n"));
ASSERT(m_pGridCtrl);
if (pWnd->GetSafeHwnd() == m_pGridCtrl->GetSafeHwnd())
return m_pGridCtrl->OnDrop(pDataObject, dropEffect, point);
else
return FALSE;
}
#endif // GRIDCONTROL_NO_DRAGDROP

View File

@@ -0,0 +1,82 @@
//////////////////////////////////////////////////////////////////////
// GridDropTarget.h : header file
//
// MFC Grid Control - Drag/Drop target implementation
//
// Written by Chris Maunder <cmaunder@mail.com>
// Copyright (c) 1998-2002. All Rights Reserved.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.10+
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_GRIDDROPTARGET_H__5C610981_BD36_11D1_97CD_00A0243D1382__INCLUDED_)
#define AFX_GRIDDROPTARGET_H__5C610981_BD36_11D1_97CD_00A0243D1382__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#include <afxole.h>
class CGridCtrl;
/////////////////////////////////////////////////////////////////////////////
// CGridDropTarget command target
class AFX_EXT_CLASS CGridDropTarget : public COleDropTarget
{
public:
CGridDropTarget();
virtual ~CGridDropTarget();
// Attributes
public:
CGridCtrl* m_pGridCtrl;
BOOL m_bRegistered;
// Operations
public:
BOOL Register(CGridCtrl *pGridCtrl);
virtual void Revoke();
BOOL OnDrop(CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point);
DROPEFFECT OnDragEnter(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point);
void OnDragLeave(CWnd* pWnd);
DROPEFFECT OnDragOver(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point);
DROPEFFECT OnDragScroll(CWnd* pWnd, DWORD dwKeyState, CPoint point);
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CGridDropTarget)
//}}AFX_VIRTUAL
// Implementation
protected:
// Generated message map functions
//{{AFX_MSG(CGridDropTarget)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_GRIDDROPTARGET_H__5C610981_BD36_11D1_97CD_00A0243D1382__INCLUDED_)

View File

@@ -0,0 +1,263 @@
// InPlaceEdit.cpp : implementation file
//
// Adapted by Chris Maunder <cmaunder@mail.com>
// Copyright (c) 1998-2002. All Rights Reserved.
//
// The code contained in this file is based on the original
// CInPlaceEdit from http://www.codeguru.com/listview/edit_subitems.shtml
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.10+
//
// History:
// 10 May 1998 Uses GVN_ notifications instead of LVN_,
// Sends notification messages to the parent,
// instead of the parent's parent.
// 15 May 1998 There was a problem when editing with the in-place editor,
// there arises a general protection fault in user.exe, with a
// few qualifications:
// (1) This only happens with owner-drawn buttons;
// (2) This only happens in Win95
// (3) This only happens if the handler for the button does not
// create a new window (even an AfxMessageBox will avoid the
// crash)
// (4) This will not happen if Spy++ is running.
// PreTranslateMessage was added to route messages correctly.
// (Matt Weagle found and fixed this problem)
// 26 Jul 1998 Removed the ES_MULTILINE style - that fixed a few probs!
// 6 Aug 1998 Added nID to the constructor param list
// 6 Sep 1998 Space no longer clears selection when starting edit (Franco Bez)
// 10 Apr 1999 Enter, Tab and Esc key prob fixed (Koay Kah Hoe)
// Workaround for bizzare "shrinking window" problem in CE
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "TCHAR.h"
#include "InPlaceEdit.h"
#include "GridCtrl.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CInPlaceEdit
CInPlaceEdit::CInPlaceEdit(CWnd* pParent, CRect& rect, DWORD dwStyle, UINT nID,
int nRow, int nColumn, CString sInitText,
UINT nFirstChar)
{
m_sInitText = sInitText;
m_nRow = nRow;
m_nColumn = nColumn;
m_nLastChar = 0;
m_bExitOnArrows = (nFirstChar != VK_LBUTTON); // If mouse click brought us here,
// then no exit on arrows
m_Rect = rect; // For bizarre CE bug.
DWORD dwEditStyle = WS_BORDER|WS_CHILD|WS_VISIBLE| ES_AUTOHSCROLL //|ES_MULTILINE
| dwStyle;
if (!Create(dwEditStyle, rect, pParent, nID)) return;
SetFont(pParent->GetFont());
SetWindowText(sInitText);
SetFocus();
switch (nFirstChar){
case VK_LBUTTON:
case VK_RETURN: SetSel((int)_tcslen(m_sInitText), -1); return;
case VK_BACK: SetSel((int)_tcslen(m_sInitText), -1); break;
case VK_TAB:
case VK_DOWN:
case VK_UP:
case VK_RIGHT:
case VK_LEFT:
case VK_NEXT:
case VK_PRIOR:
case VK_HOME:
case VK_SPACE:
case VK_END: SetSel(0,-1); return;
default: SetSel(0,-1);
}
// Added by KiteFly. When entering DBCS chars into cells the first char was being lost
// SenMessage changed to PostMessage (John Lagerquist)
if( nFirstChar < 0x80)
PostMessage(WM_CHAR, nFirstChar);
else
PostMessage(WM_IME_CHAR, nFirstChar);
}
CInPlaceEdit::~CInPlaceEdit()
{
}
BEGIN_MESSAGE_MAP(CInPlaceEdit, CEdit)
//{{AFX_MSG_MAP(CInPlaceEdit)
ON_WM_KILLFOCUS()
ON_WM_CHAR()
ON_WM_KEYDOWN()
ON_WM_GETDLGCODE()
ON_WM_CREATE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
////////////////////////////////////////////////////////////////////////////
// CInPlaceEdit message handlers
// If an arrow key (or associated) is pressed, then exit if
// a) The Ctrl key was down, or
// b) m_bExitOnArrows == TRUE
void CInPlaceEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if ((nChar == VK_PRIOR || nChar == VK_NEXT ||
nChar == VK_DOWN || nChar == VK_UP ||
nChar == VK_RIGHT || nChar == VK_LEFT) &&
(m_bExitOnArrows || GetKeyState(VK_CONTROL) < 0))
{
m_nLastChar = nChar;
GetParent()->SetFocus();
return;
}
CEdit::OnKeyDown(nChar, nRepCnt, nFlags);
}
// As soon as this edit loses focus, kill it.
void CInPlaceEdit::OnKillFocus(CWnd* pNewWnd)
{
CEdit::OnKillFocus(pNewWnd);
EndEdit();
}
void CInPlaceEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if (nChar == VK_TAB || nChar == VK_RETURN)
{
m_nLastChar = nChar;
GetParent()->SetFocus(); // This will destroy this window
return;
}
if (nChar == VK_ESCAPE)
{
SetWindowText(m_sInitText); // restore previous text
m_nLastChar = nChar;
GetParent()->SetFocus();
return;
}
CEdit::OnChar(nChar, nRepCnt, nFlags);
// Resize edit control if needed
// Get text extent
CString str;
GetWindowText( str );
// add some extra buffer
str += _T(" ");
CWindowDC dc(this);
CFont *pFontDC = dc.SelectObject(GetFont());
CSize size = dc.GetTextExtent( str );
dc.SelectObject( pFontDC );
// Get client rect
CRect ParentRect;
GetParent()->GetClientRect( &ParentRect );
// Check whether control needs to be resized
// and whether there is space to grow
if (size.cx > m_Rect.Width())
{
if( size.cx + m_Rect.left < ParentRect.right )
m_Rect.right = m_Rect.left + size.cx;
else
m_Rect.right = ParentRect.right;
MoveWindow( &m_Rect );
}
}
UINT CInPlaceEdit::OnGetDlgCode()
{
return DLGC_WANTALLKEYS;
}
////////////////////////////////////////////////////////////////////////////
// CInPlaceEdit overrides
// Stoopid win95 accelerator key problem workaround - Matt Weagle.
BOOL CInPlaceEdit::PreTranslateMessage(MSG* pMsg)
{
// Catch the Alt key so we don't choke if focus is going to an owner drawn button
if (pMsg->message == WM_SYSCHAR)
return TRUE;
return CWnd::PreTranslateMessage(pMsg);
}
// Auto delete
void CInPlaceEdit::PostNcDestroy()
{
CEdit::PostNcDestroy();
delete this;
}
////////////////////////////////////////////////////////////////////////////
// CInPlaceEdit implementation
void CInPlaceEdit::EndEdit()
{
CString str;
// EFW - BUG FIX - Clicking on a grid scroll bar in a derived class
// that validates input can cause this to get called multiple times
// causing assertions because the edit control goes away the first time.
static BOOL bAlreadyEnding = FALSE;
if(bAlreadyEnding)
return;
bAlreadyEnding = TRUE;
GetWindowText(str);
// Send Notification to parent
GV_DISPINFO dispinfo;
dispinfo.hdr.hwndFrom = GetSafeHwnd();
dispinfo.hdr.idFrom = GetDlgCtrlID();
dispinfo.hdr.code = GVN_ENDLABELEDIT;
dispinfo.item.mask = LVIF_TEXT|LVIF_PARAM;
dispinfo.item.row = m_nRow;
dispinfo.item.col = m_nColumn;
dispinfo.item.strText = str;
dispinfo.item.lParam = (LPARAM) m_nLastChar;
CWnd* pOwner = GetOwner();
if (pOwner)
pOwner->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&dispinfo );
// Close this window (PostNcDestroy will delete this)
if (IsWindow(GetSafeHwnd()))
SendMessage(WM_CLOSE, 0, 0);
bAlreadyEnding = FALSE;
}

View File

@@ -0,0 +1,83 @@
//////////////////////////////////////////////////////////////////////
// InPlaceEdit.h : header file
//
// MFC Grid Control - inplace editing class
//
// Written by Chris Maunder <cmaunder@mail.com>
// Copyright (c) 1998-2002. All Rights Reserved.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.10+
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_INPLACEEDIT_H__ECD42821_16DF_11D1_992F_895E185F9C72__INCLUDED_)
#define AFX_INPLACEEDIT_H__ECD42821_16DF_11D1_992F_895E185F9C72__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
class AFX_EXT_CLASS CInPlaceEdit : public CEdit
{
// Construction
public:
CInPlaceEdit(CWnd* pParent, CRect& rect, DWORD dwStyle, UINT nID,
int nRow, int nColumn, CString sInitText, UINT nFirstChar);
// Attributes
public:
// Operations
public:
void EndEdit();
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CInPlaceEdit)
public:
virtual BOOL PreTranslateMessage(MSG* pMsg);
protected:
virtual void PostNcDestroy();
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CInPlaceEdit();
// Generated message map functions
protected:
//{{AFX_MSG(CInPlaceEdit)
afx_msg void OnKillFocus(CWnd* pNewWnd);
afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg UINT OnGetDlgCode();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
int m_nRow;
int m_nColumn;
CString m_sInitText;
UINT m_nLastChar;
BOOL m_bExitOnArrows;
CRect m_Rect;
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_INPLACEEDIT_H__ECD42821_16DF_11D1_992F_895E185F9C72__INCLUDED_)

View File

@@ -0,0 +1,106 @@
#if !defined(AFX_MEMDC_H__CA1D3541_7235_11D1_ABBA_00A0243D1382__INCLUDED_)
#define AFX_MEMDC_H__CA1D3541_7235_11D1_ABBA_00A0243D1382__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// MemDC.h : header file
//
//////////////////////////////////////////////////
// CMemDC - memory DC
//
// Author: Keith Rule
// Email: keithr@europa.com
// Copyright 1996-1997, Keith Rule
//
// You may freely use or modify this code provided this
// Copyright is included in all derived versions.
//
// History - 10/3/97 Fixed scrolling bug.
// Added print support.
// 25 feb 98 - fixed minor assertion bug
//
// This class implements a memory Device Context
class AFX_EXT_CLASS CMemDC : public CDC
{
public:
// constructor sets up the memory DC
CMemDC(CDC* pDC) : CDC()
{
ASSERT(pDC != NULL);
m_pDC = pDC;
m_pOldBitmap = NULL;
#ifndef _WIN32_WCE_NO_PRINTING
m_bMemDC = !pDC->IsPrinting();
#else
m_bMemDC = FALSE;
#endif
if (m_bMemDC) // Create a Memory DC
{
pDC->GetClipBox(&m_rect);
CreateCompatibleDC(pDC);
m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height());
m_pOldBitmap = SelectObject(&m_bitmap);
#ifndef _WIN32_WCE
SetWindowOrg(m_rect.left, m_rect.top);
#endif
// EFW - Bug fix - Fill background in case the user has overridden
// WM_ERASEBKGND. We end up with garbage otherwise.
// CJM - moved to fix a bug in the fix.
FillSolidRect(m_rect, pDC->GetBkColor());
}
else // Make a copy of the relevent parts of the current DC for printing
{
#if !defined(_WIN32_WCE) || ((_WIN32_WCE > 201) && !defined(_WIN32_WCE_NO_PRINTING))
m_bPrinting = pDC->m_bPrinting;
#endif
m_hDC = pDC->m_hDC;
m_hAttribDC = pDC->m_hAttribDC;
}
}
// Destructor copies the contents of the mem DC to the original DC
~CMemDC()
{
if (m_bMemDC)
{
// Copy the offscreen bitmap onto the screen.
m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(),
this, m_rect.left, m_rect.top, SRCCOPY);
//Swap back the original bitmap.
SelectObject(m_pOldBitmap);
} else {
// All we need to do is replace the DC with an illegal value,
// this keeps us from accidently deleting the handles associated with
// the CDC that was passed to the constructor.
m_hDC = m_hAttribDC = NULL;
}
}
// Allow usage as a pointer
CMemDC* operator->() {return this;}
// Allow usage as a pointer
operator CMemDC*() {return this;}
private:
CBitmap m_bitmap; // Offscreen bitmap
CBitmap* m_pOldBitmap; // bitmap originally found in CMemDC
CDC* m_pDC; // Saves CDC passed in constructor
CRect m_rect; // Rectangle of drawing area.
BOOL m_bMemDC; // TRUE if CDC really is a Memory DC.
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_MEMDC_H__CA1D3541_7235_11D1_ABBA_00A0243D1382__INCLUDED_)

View File

@@ -0,0 +1,341 @@
////////////////////////////////////////////////////////////////////////////
// TitleTip.cpp : implementation file
//
// Based on code by Zafir Anjum
//
// Adapted by Chris Maunder <cmaunder@mail.com>
// Copyright (c) 1998-2002. All Rights Reserved.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.20+
//
// History
// 10 Apr 1999 Now accepts a LOGFONT pointer and
// a tracking rect in Show(...) (Chris Maunder)
// 18 Apr 1999 Resource leak in Show fixed by Daniel Gehriger
// 8 Mar 2000 Added double-click fix found on codeguru
// web site but forgot / can't find who contributed it
// 28 Mar 2000 Aqiruse (marked with //FNA)
// Titletips now use cell color
// 18 Jun 2000 Delayed window creation added
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "gridctrl.h"
#ifndef GRIDCONTROL_NO_TITLETIPS
#include "TitleTip.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CTitleTip
CTitleTip::CTitleTip()
{
// Register the window class if it has not already been registered.
WNDCLASS wndcls;
HINSTANCE hInst = AfxGetInstanceHandle();
if(!(::GetClassInfo(hInst, TITLETIP_CLASSNAME, &wndcls)))
{
// otherwise we need to register a new class
wndcls.style = CS_SAVEBITS;
wndcls.lpfnWndProc = ::DefWindowProc;
wndcls.cbClsExtra = wndcls.cbWndExtra = 0;
wndcls.hInstance = hInst;
wndcls.hIcon = NULL;
wndcls.hCursor = LoadCursor( hInst, IDC_ARROW );
wndcls.hbrBackground = (HBRUSH)(COLOR_INFOBK +1);
wndcls.lpszMenuName = NULL;
wndcls.lpszClassName = TITLETIP_CLASSNAME;
if (!AfxRegisterClass(&wndcls))
AfxThrowResourceException();
}
m_dwLastLButtonDown = ULONG_MAX;
m_dwDblClickMsecs = GetDoubleClickTime();
m_bCreated = FALSE;
m_pParentWnd = NULL;
}
CTitleTip::~CTitleTip()
{
}
BEGIN_MESSAGE_MAP(CTitleTip, CWnd)
//{{AFX_MSG_MAP(CTitleTip)
ON_WM_MOUSEMOVE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTitleTip message handlers
BOOL CTitleTip::Create(CWnd * pParentWnd)
{
ASSERT_VALID(pParentWnd);
// Already created?
if (m_bCreated)
return TRUE;
DWORD dwStyle = WS_BORDER | WS_POPUP;
DWORD dwExStyle = WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
m_pParentWnd = pParentWnd;
m_bCreated = CreateEx(dwExStyle, TITLETIP_CLASSNAME, NULL, dwStyle,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, NULL );
return m_bCreated;
}
BOOL CTitleTip::DestroyWindow()
{
m_bCreated = FALSE;
return CWnd::DestroyWindow();
}
// Show - Show the titletip if needed
// rectTitle - The rectangle within which the original
// title is constrained - in client coordinates
// lpszTitleText - The text to be displayed
// xoffset - Number of pixel that the text is offset from
// left border of the cell
void CTitleTip::Show(CRect rectTitle, LPCTSTR lpszTitleText, int xoffset /*=0*/,
LPRECT lpHoverRect /*=NULL*/,
const LOGFONT* lpLogFont /*=NULL*/,
COLORREF crTextClr /* CLR_DEFAULT */,
COLORREF crBackClr /* CLR_DEFAULT */)
{
if (!IsWindow(m_hWnd))
Create(m_pParentWnd);
ASSERT( ::IsWindow( GetSafeHwnd() ) );
if (rectTitle.IsRectEmpty())
return;
// If titletip is already displayed, don't do anything.
if( IsWindowVisible() )
return;
m_rectHover = (lpHoverRect != NULL)? lpHoverRect : rectTitle;
m_rectHover.right++; m_rectHover.bottom++;
m_pParentWnd->ClientToScreen( m_rectHover );
ScreenToClient( m_rectHover );
// Do not display the titletip is app does not have focus
if( GetFocus() == NULL )
return;
// Define the rectangle outside which the titletip will be hidden.
// We add a buffer of one pixel around the rectangle
m_rectTitle.top = -1;
m_rectTitle.left = -xoffset-1;
m_rectTitle.right = rectTitle.Width()-xoffset;
m_rectTitle.bottom = rectTitle.Height()+1;
// Determine the width of the text
m_pParentWnd->ClientToScreen( rectTitle );
CClientDC dc(this);
CString strTitle = _T("");
strTitle += _T(" ");
strTitle += lpszTitleText;
strTitle += _T(" ");
CFont font, *pOldFont = NULL;
if (lpLogFont)
{
font.CreateFontIndirect(lpLogFont);
pOldFont = dc.SelectObject( &font );
}
else
{
// use same font as ctrl
pOldFont = dc.SelectObject( m_pParentWnd->GetFont() );
}
CSize size = dc.GetTextExtent( strTitle );
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);
size.cx += tm.tmOverhang;
CRect rectDisplay = rectTitle;
rectDisplay.left += xoffset;
rectDisplay.right = rectDisplay.left + size.cx + xoffset;
// Do not display if the text fits within available space
if ( rectDisplay.right > rectTitle.right-xoffset )
{
// Show the titletip
SetWindowPos( &wndTop, rectDisplay.left, rectDisplay.top,
rectDisplay.Width(), rectDisplay.Height(),
SWP_SHOWWINDOW|SWP_NOACTIVATE );
// FNA - handle colors correctly
if (crBackClr != CLR_DEFAULT)
{
CBrush backBrush(crBackClr);
CBrush* pOldBrush = dc.SelectObject(&backBrush);
CRect rect;
dc.GetClipBox(&rect); // Erase the area needed
dc.PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY);
dc.SelectObject(pOldBrush);
}
// Set color
if (crTextClr != CLR_DEFAULT)//FNA
dc.SetTextColor(crTextClr);//FA
dc.SetBkMode( TRANSPARENT );
dc.TextOut( 0, 0, strTitle );
SetCapture();
}
dc.SelectObject( pOldFont );
}
void CTitleTip::Hide()
{
if (!::IsWindow(GetSafeHwnd()))
return;
if (GetCapture()->GetSafeHwnd() == GetSafeHwnd())
ReleaseCapture();
ShowWindow( SW_HIDE );
}
void CTitleTip::OnMouseMove(UINT nFlags, CPoint point)
{
if (!m_rectHover.PtInRect(point))
{
Hide();
// Forward the message
ClientToScreen( &point );
CWnd *pWnd = WindowFromPoint( point );
if ( pWnd == this )
pWnd = m_pParentWnd;
int hittest = (int)pWnd->SendMessage(WM_NCHITTEST,0,MAKELONG(point.x,point.y));
if (hittest == HTCLIENT) {
pWnd->ScreenToClient( &point );
pWnd->PostMessage( WM_MOUSEMOVE, nFlags, MAKELONG(point.x,point.y) );
} else {
pWnd->PostMessage( WM_NCMOUSEMOVE, hittest, MAKELONG(point.x,point.y) );
}
}
}
BOOL CTitleTip::PreTranslateMessage(MSG* pMsg)
{
// Used to qualify WM_LBUTTONDOWN messages as double-clicks
DWORD dwTick=0;
BOOL bDoubleClick=FALSE;
CWnd *pWnd;
int hittest;
switch (pMsg->message)
{
case WM_LBUTTONDOWN:
// Get tick count since last LButtonDown
dwTick = GetTickCount();
bDoubleClick = ((dwTick - m_dwLastLButtonDown) <= m_dwDblClickMsecs);
m_dwLastLButtonDown = dwTick;
// NOTE: DO NOT ADD break; STATEMENT HERE! Let code fall through
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
{
POINTS pts = MAKEPOINTS( pMsg->lParam );
POINT point;
point.x = pts.x;
point.y = pts.y;
ClientToScreen( &point );
Hide();
pWnd = WindowFromPoint( point );
if (!pWnd)
return CWnd::PreTranslateMessage(pMsg);
if( pWnd->GetSafeHwnd() == GetSafeHwnd())
pWnd = m_pParentWnd;
hittest = (int)pWnd->SendMessage(WM_NCHITTEST,0,MAKELONG(point.x,point.y));
if (hittest == HTCLIENT)
{
pWnd->ScreenToClient( &point );
pMsg->lParam = MAKELONG(point.x,point.y);
}
else
{
switch (pMsg->message) {
case WM_LBUTTONDOWN:
pMsg->message = WM_NCLBUTTONDOWN;
break;
case WM_RBUTTONDOWN:
pMsg->message = WM_NCRBUTTONDOWN;
break;
case WM_MBUTTONDOWN:
pMsg->message = WM_NCMBUTTONDOWN;
break;
}
pMsg->wParam = hittest;
pMsg->lParam = MAKELONG(point.x,point.y);
}
// If this is the 2nd WM_LBUTTONDOWN in x milliseconds,
// post a WM_LBUTTONDBLCLK message instead of a single click.
pWnd->PostMessage( bDoubleClick ? WM_LBUTTONDBLCLK : pMsg->message,
pMsg->wParam,
pMsg->lParam);
return TRUE;
}
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
Hide();
m_pParentWnd->PostMessage( pMsg->message, pMsg->wParam, pMsg->lParam );
return TRUE;
}
if( GetFocus() == NULL )
{
Hide();
return TRUE;
}
return CWnd::PreTranslateMessage(pMsg);
}
#endif // GRIDCONTROL_NO_TITLETIPS

View File

@@ -0,0 +1,87 @@
/////////////////////////////////////////////////////////////////////////////
// Titletip.h : header file
//
// MFC Grid Control - cell titletips
//
// Written by Chris Maunder <cmaunder@mail.com>
// Copyright (c) 1998-2001. All Rights Reserved.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.10+
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_TITLETIP_H__C7165DA1_187F_11D1_992F_895E185F9C72__INCLUDED_)
#define AFX_TITLETIP_H__C7165DA1_187F_11D1_992F_895E185F9C72__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#define TITLETIP_CLASSNAME _T("ZTitleTip")
/////////////////////////////////////////////////////////////////////////////
// CTitleTip window
class AFX_EXT_CLASS CTitleTip : public CWnd
{
// Construction
public:
CTitleTip();
virtual ~CTitleTip();
virtual BOOL Create( CWnd *pParentWnd);
// Attributes
public:
void SetParentWnd(CWnd* pParentWnd) { m_pParentWnd = pParentWnd; }
CWnd* GetParentWnd() { return m_pParentWnd; }
// Operations
public:
void Show(CRect rectTitle, LPCTSTR lpszTitleText,
int xoffset = 0, LPRECT lpHoverRect = NULL,
const LOGFONT* lpLogFont = NULL,
COLORREF crTextClr = CLR_DEFAULT, COLORREF crBackClr = CLR_DEFAULT);
void Hide();
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CTitleTip)
public:
virtual BOOL PreTranslateMessage(MSG* pMsg);
virtual BOOL DestroyWindow();
//}}AFX_VIRTUAL
// Implementation
protected:
CWnd *m_pParentWnd;
CRect m_rectTitle;
CRect m_rectHover;
DWORD m_dwLastLButtonDown;
DWORD m_dwDblClickMsecs;
BOOL m_bCreated;
// Generated message map functions
protected:
//{{AFX_MSG(CTitleTip)
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_TITLETIP_H__C7165DA1_187F_11D1_992F_895E185F9C72__INCLUDED_)

View File

@@ -0,0 +1,160 @@
// GridCellCheck.cpp : implementation file
//
// MFC Grid Control - Main grid cell class
//
// Provides the implementation for a combobox cell type of the
// grid control.
//
// Written by Chris Maunder <cmaunder@mail.com>
// Copyright (c) 1998-2002. All Rights Reserved.
//
// Parts of the code contained in this file are based on the original
// CInPlaceList from http://www.codeguru.com/listview
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.22+
//
// History:
// 23 Jul 2001 - Complete rewrite
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "../GridCtrl_src/GridCell.h"
#include "../GridCtrl_src/GridCtrl.h"
#include "GridCellCheck.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNCREATE(CGridCellCheck, CGridCell)
CGridCellCheck::CGridCellCheck() : CGridCell()
{
m_bChecked = FALSE;
//m_Rect.IsRectNull();
}
CSize CGridCellCheck::GetCellExtent(CDC* pDC)
{
// Using SM_CXHSCROLL as a guide to the size of the checkbox
int nWidth = GetSystemMetrics(SM_CXHSCROLL) + 2*GetMargin();
return CGridCell::GetCellExtent(pDC) + CSize(nWidth, nWidth);
}
// i/o: i=dims of cell rect; o=dims of text rect
BOOL CGridCellCheck::GetTextRect( LPRECT pRect)
{
BOOL bResult = CGridCell::GetTextRect(pRect);
if (bResult)
{
int nWidth = GetSystemMetrics(SM_CXHSCROLL) + 2*GetMargin();
pRect->left += nWidth;
if (pRect->left > pRect->right)
pRect->left = pRect->right;
}
return bResult;
}
// Override draw so that when the cell is selected, a drop arrow is shown in the RHS.
BOOL CGridCellCheck::Draw(CDC* pDC, int nRow, int nCol, CRect rect, BOOL bEraseBkgnd /*=TRUE*/)
{
BOOL bResult = CGridCell::Draw(pDC, nRow, nCol, rect, bEraseBkgnd);
#ifndef _WIN32_WCE
// Store the cell's dimensions for later
m_Rect = rect;
CRect CheckRect = GetCheckPlacement();
rect.left = CheckRect.right;
// enough room to draw?
// if (CheckRect.Width() < rect.Width() && CheckRect.Height() < rect.Height()) {
// Do the draw
pDC->DrawFrameControl(GetCheckPlacement(), DFC_BUTTON,
(m_bChecked)? DFCS_BUTTONCHECK | DFCS_CHECKED : DFCS_BUTTONCHECK);
// }
#endif
return bResult;
}
void CGridCellCheck::OnClick(CPoint PointCellRelative)
{
// PointCellRelative is relative to the topleft of the cell. Convert to client coords
PointCellRelative += m_Rect.TopLeft();
// GetCheckPlacement returns the checkbox dimensions in client coords. Only check/
// uncheck if the user clicked in the box
if (GetCheckPlacement().PtInRect(PointCellRelative))
{
m_bChecked = !m_bChecked;
GetGrid()->InvalidateRect(m_Rect);
}
}
//////////////////////////////////////////////////////////////////////
// Operations
//////////////////////////////////////////////////////////////////////
BOOL CGridCellCheck::SetCheck(BOOL bChecked /*=TRUE*/)
{
BOOL bTemp = m_bChecked;
m_bChecked = bChecked;
if (!m_Rect.IsRectEmpty())
GetGrid()->InvalidateRect(m_Rect);
return bTemp;
}
BOOL CGridCellCheck::GetCheck()
{
return m_bChecked;
}
//////////////////////////////////////////////////////////////////////
// Protected implementation
//////////////////////////////////////////////////////////////////////
// Returns the dimensions and placement of the checkbox in client coords.
CRect CGridCellCheck::GetCheckPlacement()
{
int nWidth = GetSystemMetrics(SM_CXHSCROLL);
CRect place = m_Rect + CSize(GetMargin(), GetMargin());
place.right = place.left + nWidth;
place.bottom = place.top + nWidth;
/* for centering
int nDiff = (place.Width() - nWidth)/2;
if (nDiff > 0)
{
place.left += nDiff;
place.right = place.left + nWidth;
}
nDiff = (place.Height() - nWidth)/2;
if (nDiff > 0)
{
place.top += nDiff;
place.bottom = place.top + nWidth;
}
*/
return place;
}

View File

@@ -0,0 +1,68 @@
#if !defined(AFX_GRIDCELLCHECK_H__ECD42822_16DF_11D1_992F_895E185F9C72__INCLUDED_)
#define AFX_GRIDCELLCHECK_H__ECD42822_16DF_11D1_992F_895E185F9C72__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
/////////////////////////////////////////////////////////////////////////////
// GridCellCheck.h : header file
//
// MFC Grid Control - Grid combo cell class header file
//
// Written by Chris Maunder <cmaunder@mail.com>
// Copyright (c) 1998-2002. All Rights Reserved.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.22+
//
//////////////////////////////////////////////////////////////////////
#include "../GridCtrl_src/GridCell.h"
class AFX_EXT_CLASS CGridCellCheck : public CGridCell
{
friend class CGridCtrl;
DECLARE_DYNCREATE(CGridCellCheck)
public:
CGridCellCheck();
public:
BOOL SetCheck(BOOL bChecked = TRUE);
BOOL GetCheck();
// Operations
virtual CSize GetCellExtent(CDC* pDC);
virtual void OnClick( CPoint PointCellRelative);
virtual BOOL GetTextRect( LPRECT pRect);
protected:
CRect GetCheckPlacement();
virtual BOOL Draw(CDC* pDC, int nRow, int nCol, CRect rect, BOOL bEraseBkgnd = TRUE);
protected:
BOOL m_bChecked;
CRect m_Rect;
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_GRIDCELLCHECK_H__ECD42822_16DF_11D1_992F_895E185F9C72__INCLUDED_)

View File

@@ -0,0 +1,483 @@
// GridCellCombo.cpp : implementation file
//
// MFC Grid Control - Main grid cell class
//
// Provides the implementation for a combobox cell type of the
// grid control.
//
// Written by Chris Maunder <cmaunder@mail.com>
// Copyright (c) 1998-2001. All Rights Reserved.
//
// Parts of the code contained in this file are based on the original
// CInPlaceList from http://www.codeguru.com/listview
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.22+
//
// History:
// 6 Aug 1998 - Added CComboEdit to subclass the edit control - code
// provided by Roelf Werkman <rdw@inn.nl>. Added nID to
// the constructor param list.
// 29 Nov 1998 - bug fix in onkeydown (Markus Irtenkauf)
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "../GridCtrl_src/GridCell.h"
#include "../GridCtrl_src/GridCtrl.h"
#include "GridCellCombo.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CComboEdit
CComboEdit::CComboEdit()
{
}
CComboEdit::~CComboEdit()
{
}
// Stoopid win95 accelerator key problem workaround - Matt Weagle.
BOOL CComboEdit::PreTranslateMessage(MSG* pMsg)
{
// Make sure that the keystrokes continue to the appropriate handlers
if (pMsg->message == WM_KEYDOWN || pMsg->message == WM_KEYUP)
{
::TranslateMessage(pMsg);
::DispatchMessage(pMsg);
return TRUE;
}
// Catch the Alt key so we don't choke if focus is going to an owner drawn button
if (pMsg->message == WM_SYSCHAR)
return TRUE;
return CEdit::PreTranslateMessage(pMsg);
}
BEGIN_MESSAGE_MAP(CComboEdit, CEdit)
//{{AFX_MSG_MAP(CComboEdit)
ON_WM_KILLFOCUS()
ON_WM_KEYDOWN()
ON_WM_KEYUP()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CComboEdit message handlers
void CComboEdit::OnKillFocus(CWnd* pNewWnd)
{
CEdit::OnKillFocus(pNewWnd);
CInPlaceList* pOwner = (CInPlaceList*) GetOwner(); // This MUST be a CInPlaceList
if (pOwner)
pOwner->EndEdit();
}
void CComboEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if ((nChar == VK_PRIOR || nChar == VK_NEXT ||
nChar == VK_DOWN || nChar == VK_UP ||
nChar == VK_RIGHT || nChar == VK_LEFT) &&
(GetKeyState(VK_CONTROL) < 0 && GetDlgCtrlID() == IDC_COMBOEDIT))
{
CWnd* pOwner = GetOwner();
if (pOwner)
pOwner->SendMessage(WM_KEYDOWN, nChar, nRepCnt+ (((DWORD)nFlags)<<16));
return;
}
CEdit::OnKeyDown(nChar, nRepCnt, nFlags);
}
void CComboEdit::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if (nChar == VK_ESCAPE)
{
CWnd* pOwner = GetOwner();
if (pOwner)
pOwner->SendMessage(WM_KEYUP, nChar, nRepCnt + (((DWORD)nFlags)<<16));
return;
}
if (nChar == VK_TAB || nChar == VK_RETURN || nChar == VK_ESCAPE)
{
CWnd* pOwner = GetOwner();
if (pOwner)
pOwner->SendMessage(WM_KEYUP, nChar, nRepCnt + (((DWORD)nFlags)<<16));
return;
}
CEdit::OnKeyUp(nChar, nRepCnt, nFlags);
}
/////////////////////////////////////////////////////////////////////////////
// CInPlaceList
CInPlaceList::CInPlaceList(CWnd* pParent, CRect& rect, DWORD dwStyle, UINT nID,
int nRow, int nColumn,
COLORREF crFore, COLORREF crBack,
CStringArray& Items, CString sInitText,
UINT nFirstChar)
{
m_crForeClr = crFore;
m_crBackClr = crBack;
m_nNumLines = 4;
m_sInitText = sInitText;
m_nRow = nRow;
m_nCol = nColumn;
m_nLastChar = 0;
m_bExitOnArrows = FALSE; //(nFirstChar != VK_LBUTTON); // If mouse click brought us here,
// Create the combobox
DWORD dwComboStyle = WS_BORDER|WS_CHILD|WS_VISIBLE|WS_VSCROLL|
CBS_AUTOHSCROLL | dwStyle;
int nHeight = rect.Height();
rect.bottom = rect.bottom + m_nNumLines*nHeight + ::GetSystemMetrics(SM_CYHSCROLL);
if (!Create(dwComboStyle, rect, pParent, nID)) return;
// Add the strings
for (int i = 0; i < Items.GetSize(); i++)
AddString(Items[i]);
SetFont(pParent->GetFont());
SetItemHeight(-1, nHeight);
int nMaxLength = GetCorrectDropWidth();
/*
if (nMaxLength > rect.Width())
rect.right = rect.left + nMaxLength;
// Resize the edit window and the drop down window
MoveWindow(rect);
*/
SetDroppedWidth(nMaxLength);
SetHorizontalExtent(0); // no horz scrolling
// Set the initial text to m_sInitText
if (::IsWindow(m_hWnd) && SelectString(-1, m_sInitText) == CB_ERR)
SetWindowText(m_sInitText); // No text selected, so restore what was there before
ShowDropDown();
// Subclass the combobox edit control if style includes CBS_DROPDOWN
if ((dwStyle & CBS_DROPDOWNLIST) != CBS_DROPDOWNLIST)
{
m_edit.SubclassDlgItem(IDC_COMBOEDIT, this);
SetFocus();
switch (nFirstChar)
{
case VK_LBUTTON:
case VK_RETURN: m_edit.SetSel((int)_tcslen(m_sInitText), -1); return;
case VK_BACK: m_edit.SetSel((int)_tcslen(m_sInitText), -1); break;
case VK_DOWN:
case VK_UP:
case VK_RIGHT:
case VK_LEFT:
case VK_NEXT:
case VK_PRIOR:
case VK_HOME:
case VK_END: m_edit.SetSel(0,-1); return;
default: m_edit.SetSel(0,-1);
}
SendMessage(WM_CHAR, nFirstChar);
}
else
SetFocus();
}
CInPlaceList::~CInPlaceList()
{
}
void CInPlaceList::EndEdit()
{
CString str;
if (::IsWindow(m_hWnd))
GetWindowText(str);
// Send Notification to parent
GV_DISPINFO dispinfo;
dispinfo.hdr.hwndFrom = GetSafeHwnd();
dispinfo.hdr.idFrom = GetDlgCtrlID();
dispinfo.hdr.code = GVN_ENDLABELEDIT;
dispinfo.item.mask = LVIF_TEXT|LVIF_PARAM;
dispinfo.item.row = m_nRow;
dispinfo.item.col = m_nCol;
dispinfo.item.strText = str;
dispinfo.item.lParam = (LPARAM) m_nLastChar;
CWnd* pOwner = GetOwner();
if (IsWindow(pOwner->GetSafeHwnd()))
pOwner->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&dispinfo );
// Close this window (PostNcDestroy will delete this)
if (::IsWindow(m_hWnd))
PostMessage(WM_CLOSE, 0, 0);
}
int CInPlaceList::GetCorrectDropWidth()
{
const int nMaxWidth = 200; // don't let the box be bigger than this
// Reset the dropped width
int nNumEntries = GetCount();
int nWidth = 0;
CString str;
CClientDC dc(this);
int nSave = dc.SaveDC();
dc.SelectObject(GetFont());
int nScrollWidth = ::GetSystemMetrics(SM_CXVSCROLL);
for (int i = 0; i < nNumEntries; i++)
{
GetLBText(i, str);
int nLength = dc.GetTextExtent(str).cx + nScrollWidth;
nWidth = max(nWidth, nLength);
}
// Add margin space to the calculations
nWidth += dc.GetTextExtent("0").cx;
dc.RestoreDC(nSave);
nWidth = min(nWidth, nMaxWidth);
return nWidth;
//SetDroppedWidth(nWidth);
}
/*
// Fix by Ray (raybie@Exabyte.COM)
void CInPlaceList::OnSelendOK()
{
int iIndex = GetCurSel();
if( iIndex != CB_ERR)
{
CString strLbText;
GetLBText( iIndex, strLbText);
if (!((GetStyle() & CBS_DROPDOWNLIST) == CBS_DROPDOWNLIST))
m_edit.SetWindowText( strLbText);
}
GetParent()->SetFocus();
}
*/
void CInPlaceList::PostNcDestroy()
{
CComboBox::PostNcDestroy();
delete this;
}
BEGIN_MESSAGE_MAP(CInPlaceList, CComboBox)
//{{AFX_MSG_MAP(CInPlaceList)
ON_WM_KILLFOCUS()
ON_WM_KEYDOWN()
ON_WM_KEYUP()
ON_CONTROL_REFLECT(CBN_DROPDOWN, OnDropdown)
ON_WM_GETDLGCODE()
ON_WM_CTLCOLOR_REFLECT()
//}}AFX_MSG_MAP
//ON_CONTROL_REFLECT(CBN_SELENDOK, OnSelendOK)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CInPlaceList message handlers
UINT CInPlaceList::OnGetDlgCode()
{
return DLGC_WANTALLKEYS;
}
void CInPlaceList::OnDropdown()
{
SetDroppedWidth(GetCorrectDropWidth());
}
void CInPlaceList::OnKillFocus(CWnd* pNewWnd)
{
CComboBox::OnKillFocus(pNewWnd);
if (GetSafeHwnd() == pNewWnd->GetSafeHwnd())
return;
// Only end editing on change of focus if we're using the CBS_DROPDOWNLIST style
if ((GetStyle() & CBS_DROPDOWNLIST) == CBS_DROPDOWNLIST)
EndEdit();
}
// If an arrow key (or associated) is pressed, then exit if
// a) The Ctrl key was down, or
// b) m_bExitOnArrows == TRUE
void CInPlaceList::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if ((nChar == VK_PRIOR || nChar == VK_NEXT ||
nChar == VK_DOWN || nChar == VK_UP ||
nChar == VK_RIGHT || nChar == VK_LEFT) &&
(m_bExitOnArrows || GetKeyState(VK_CONTROL) < 0))
{
m_nLastChar = nChar;
GetParent()->SetFocus();
return;
}
CComboBox::OnKeyDown(nChar, nRepCnt, nFlags);
}
// Need to keep a lookout for Tabs, Esc and Returns.
void CInPlaceList::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if (nChar == VK_ESCAPE)
SetWindowText(m_sInitText); // restore previous text
if (nChar == VK_TAB || nChar == VK_RETURN || nChar == VK_ESCAPE)
{
m_nLastChar = nChar;
GetParent()->SetFocus(); // This will destroy this window
return;
}
CComboBox::OnKeyUp(nChar, nRepCnt, nFlags);
}
HBRUSH CInPlaceList::CtlColor(CDC* /*pDC*/, UINT /*nCtlColor*/)
{
/*
static CBrush brush(m_crBackClr);
pDC->SetTextColor(m_crForeClr);
pDC->SetBkMode(TRANSPARENT);
return (HBRUSH) brush.GetSafeHandle();
*/
// TODO: Return a non-NULL brush if the parent's handler should not be called
return NULL;
}
/////////////////////////////////////////////////////////////////////////////
// CGridCellCombo
/////////////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNCREATE(CGridCellCombo, CGridCell)
CGridCellCombo::CGridCellCombo() : CGridCell()
{
SetStyle(CBS_DROPDOWN); // CBS_DROPDOWN, CBS_DROPDOWNLIST, CBS_SIMPLE, CBS_SORT
}
// Create a control to do the editing
BOOL CGridCellCombo::Edit(int nRow, int nCol, CRect rect, CPoint /* point */, UINT nID, UINT nChar)
{
m_bEditing = TRUE;
// CInPlaceList auto-deletes itself
m_pEditWnd = new CInPlaceList(GetGrid(), rect, GetStyle(), nID, nRow, nCol,
GetTextClr(), GetBackClr(), m_Strings, GetText(), nChar);
return TRUE;
}
CWnd* CGridCellCombo::GetEditWnd() const
{
if (m_pEditWnd && (m_pEditWnd->GetStyle() & CBS_DROPDOWNLIST) != CBS_DROPDOWNLIST )
return &(((CInPlaceList*)m_pEditWnd)->m_edit);
return NULL;
}
CSize CGridCellCombo::GetCellExtent(CDC* pDC)
{
CSize sizeScroll(GetSystemMetrics(SM_CXVSCROLL), GetSystemMetrics(SM_CYHSCROLL));
return CGridCell::GetCellExtent(pDC) + sizeScroll;
}
// Cancel the editing.
void CGridCellCombo::EndEdit()
{
if (m_pEditWnd)
((CInPlaceList*)m_pEditWnd)->EndEdit();
}
// Override draw so that when the cell is selected, a drop arrow is shown in the RHS.
BOOL CGridCellCombo::Draw(CDC* pDC, int nRow, int nCol, CRect rect, BOOL bEraseBkgnd /*=TRUE*/)
{
#ifdef _WIN32_WCE
return CGridCell::Draw(pDC, nRow, nCol, rect, bEraseBkgnd);
#else
// Cell selected?
//if ( !IsFixed() && IsFocused())
if (GetGrid()->IsCellEditable(nRow, nCol) && !IsEditing())
{
// Get the size of the scroll box
CSize sizeScroll(GetSystemMetrics(SM_CXVSCROLL), GetSystemMetrics(SM_CYHSCROLL));
// enough room to draw?
if (sizeScroll.cy < rect.Width() && sizeScroll.cy < rect.Height())
{
// Draw control at RHS of cell
CRect ScrollRect = rect;
ScrollRect.left = rect.right - sizeScroll.cx;
ScrollRect.bottom = rect.top + sizeScroll.cy;
// Do the draw
pDC->DrawFrameControl(ScrollRect, DFC_SCROLL, DFCS_SCROLLDOWN);
// Adjust the remaining space in the cell
rect.right = ScrollRect.left;
}
}
CString strTempText = GetText();
if (IsEditing())
SetText(_T(""));
// drop through and complete the cell drawing using the base class' method
BOOL bResult = CGridCell::Draw(pDC, nRow, nCol, rect, bEraseBkgnd);
if (IsEditing())
SetText(strTempText);
return bResult;
#endif
}
// For setting the strings that will be displayed in the drop list
void CGridCellCombo::SetOptions(CStringArray& ar)
{
m_Strings.RemoveAll();
for (int i = 0; i < ar.GetSize(); i++)
m_Strings.Add(ar[i]);
}

View File

@@ -0,0 +1,177 @@
#if !defined(AFX_GRIDCELLCOMBO_H__ECD42822_16DF_11D1_992F_895E185F9C72__INCLUDED_)
#define AFX_GRIDCELLCOMBO_H__ECD42822_16DF_11D1_992F_895E185F9C72__INCLUDED_
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
/////////////////////////////////////////////////////////////////////////////
// GridCellCombo.h : header file
//
// MFC Grid Control - Grid combo cell class header file
//
// Written by Chris Maunder <cmaunder@mail.com>
// Copyright (c) 1998-2002. All Rights Reserved.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name and all copyright
// notices remains intact.
//
// An email letting me know how you are using it would be nice as well.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability for any damage/loss of business that
// this product may cause.
//
// For use with CGridCtrl v2.10
//
//////////////////////////////////////////////////////////////////////
#include "../GridCtrl_src/GridCell.h"
class AFX_EXT_CLASS CGridCellCombo : public CGridCell
{
friend class CGridCtrl;
DECLARE_DYNCREATE(CGridCellCombo)
public:
CGridCellCombo();
// editing cells
public:
virtual BOOL Edit(int nRow, int nCol, CRect rect, CPoint point, UINT nID, UINT nChar);
virtual CWnd* GetEditWnd() const;
virtual void EndEdit();
// Operations
public:
virtual CSize GetCellExtent(CDC* pDC);
// CGridCellCombo specific calls
public:
void SetOptions(CStringArray& ar);
void SetStyle(DWORD dwStyle) { m_dwStyle = dwStyle; }
DWORD GetStyle() { return m_dwStyle; }
protected:
virtual BOOL Draw(CDC* pDC, int nRow, int nCol, CRect rect, BOOL bEraseBkgnd = TRUE);
CStringArray m_Strings;
DWORD m_dwStyle;
};
/////////////////////////////////////////////////////////////////////////////
// CComboEdit window
#define IDC_COMBOEDIT 1001
class AFX_EXT_CLASS CComboEdit : public CEdit
{
// Construction
public:
CComboEdit();
// Attributes
public:
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CComboEdit)
virtual BOOL PreTranslateMessage(MSG* pMsg);
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CComboEdit();
// Generated message map functions
protected:
//{{AFX_MSG(CComboEdit)
afx_msg void OnKillFocus(CWnd* pNewWnd);
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
// CInPlaceList window
class AFX_EXT_CLASS CInPlaceList : public CComboBox
{
friend class CComboEdit;
// Construction
public:
CInPlaceList(CWnd* pParent, // parent
CRect& rect, // dimensions & location
DWORD dwStyle, // window/combobox style
UINT nID, // control ID
int nRow, int nColumn, // row and column
COLORREF crFore, COLORREF crBack, // Foreground, background colour
CStringArray& Items, // Items in list
CString sInitText, // initial selection
UINT nFirstChar); // first character to pass to control
// Attributes
public:
CComboEdit m_edit; // subclassed edit control
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CInPlaceList)
protected:
virtual void PostNcDestroy();
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CInPlaceList();
void EndEdit();
protected:
int GetCorrectDropWidth();
// Generated message map functions
protected:
//{{AFX_MSG(CInPlaceList)
afx_msg void OnKillFocus(CWnd* pNewWnd);
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg void OnDropdown();
afx_msg UINT OnGetDlgCode();
afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor);
//}}AFX_MSG
//afx_msg void OnSelendOK();
DECLARE_MESSAGE_MAP()
private:
int m_nNumLines;
CString m_sInitText;
int m_nRow;
int m_nCol;
UINT m_nLastChar;
BOOL m_bExitOnArrows;
COLORREF m_crForeClr, m_crBackClr;
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_GRIDCELLCOMBO_H__ECD42822_16DF_11D1_992F_895E185F9C72__INCLUDED_)

View File

@@ -0,0 +1,257 @@
///////////////////////////////////////////////////////////////////////////
//
// GridCellDateTime.cpp: implementation of the CGridCellDateTime class.
//
// Provides the implementation for a datetime picker cell type of the
// grid control.
//
// Written by Podsypalnikov Eugen 15 Mar 2001
// Modified:
// 31 May 2001 Fixed m_cTime bug (Chris Maunder)
//
// For use with CGridCtrl v2.22+
//
///////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "../GridCtrl_src/GridCtrl.h"
#include "../GridCtrl_src/GridCell.h"
#include "GridCellDateTime.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// CGridCellDateTime
IMPLEMENT_DYNCREATE(CGridCellDateTime, CGridCell)
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CGridCellDateTime::CGridCellDateTime() : CGridCell()
{
m_dwStyle = 0;
m_cTime = CTime::GetCurrentTime();
}
CGridCellDateTime::CGridCellDateTime(DWORD dwStyle) : CGridCell()
{
Init(dwStyle);
}
CGridCellDateTime::~CGridCellDateTime()
{
}
BOOL CGridCellDateTime::Edit(int nRow, int nCol, CRect rect, CPoint /* point */,
UINT nID, UINT nChar)
{
m_bEditing = TRUE;
// CInPlaceDateTime auto-deletes itself
m_pEditWnd = new CInPlaceDateTime(GetGrid(), rect,
m_dwStyle|DTS_UPDOWN, nID, nRow, nCol,
GetTextClr(), GetBackClr(), GetTime(), nChar);
return TRUE;
}
CWnd* CGridCellDateTime::GetEditWnd() const
{
return m_pEditWnd;
}
void CGridCellDateTime::EndEdit()
{
if (m_pEditWnd) ((CInPlaceDateTime*)m_pEditWnd)->EndEdit();
}
void CGridCellDateTime::Init(DWORD dwStyle)
{
m_dwStyle = dwStyle;
SetTime(CTime::GetCurrentTime());
SetFormat(DT_CENTER|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX
#ifndef _WIN32_WCE
|DT_END_ELLIPSIS
#endif
);
}
// Should be changed to use locale settings
void CGridCellDateTime::SetTime(CTime time)
{
m_cTime = time;
if (DTS_TIMEFORMAT == m_dwStyle)
{
#ifdef _WIN32_WCE
CString strTemp;
strTemp.Format(_T("%02d:%02d:%02d"),
m_cTime.GetHour(), m_cTime.GetMinute(), m_cTime.GetSecond());
SetText(strTemp);
#else
SetText(m_cTime.Format(_T("%H:%M:%S")));
#endif
}
else if (DTS_SHORTDATEFORMAT == m_dwStyle)
{
#ifdef _WIN32_WCE
CString strTemp;
strTemp.Format(_T("%02d/%02d/%02d"),
m_cTime.GetMonth(), m_cTime.GetDay(), m_cTime.GetYear());
SetText(strTemp);
#else
SetText(m_cTime.Format(("%d/%m/%Y")));
#endif
}
}
/////////////////////////////////////////////////////////////////////////////
// CInPlaceDateTime
CInPlaceDateTime::CInPlaceDateTime(CWnd* pParent, CRect& rect, DWORD dwStyle, UINT nID,
int nRow, int nColumn,
COLORREF crFore, COLORREF crBack,
CTime* pcTime,
UINT nFirstChar)
{
m_crForeClr = crFore;
m_crBackClr = crBack;
m_nRow = nRow;
m_nCol = nColumn;
m_nLastChar = 0;
m_bExitOnArrows = FALSE;
m_pcTime = pcTime;
DWORD dwStl = WS_BORDER|WS_VISIBLE|WS_CHILD|dwStyle;
if (!Create(dwStl, rect, pParent, nID)) {
return;
}
SetTime(m_pcTime);
SetFont(pParent->GetFont());
SetFocus();
switch (nFirstChar)
{
case VK_LBUTTON:
case VK_RETURN: return;
case VK_BACK: break;
case VK_DOWN:
case VK_UP:
case VK_RIGHT:
case VK_LEFT:
case VK_NEXT:
case VK_PRIOR:
case VK_HOME:
case VK_END: return;
default: break;
}
SendMessage(WM_CHAR, nFirstChar);
}
CInPlaceDateTime::~CInPlaceDateTime()
{
}
void CInPlaceDateTime::EndEdit()
{
CString str;
if (::IsWindow(m_hWnd))
{
GetWindowText(str);
GetTime(*m_pcTime);
}
// Send Notification to parent
GV_DISPINFO dispinfo;
dispinfo.hdr.hwndFrom = GetSafeHwnd();
dispinfo.hdr.idFrom = GetDlgCtrlID();
dispinfo.hdr.code = GVN_ENDLABELEDIT;
dispinfo.item.mask = LVIF_TEXT|LVIF_PARAM;
dispinfo.item.row = m_nRow;
dispinfo.item.col = m_nCol;
dispinfo.item.strText = str;
dispinfo.item.lParam = (LPARAM) m_nLastChar;
CWnd* pOwner = GetOwner();
if (IsWindow(pOwner->GetSafeHwnd())) {
pOwner->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&dispinfo);
}
// Close this window (PostNcDestroy will delete this)
if (::IsWindow(m_hWnd)) {
PostMessage(WM_CLOSE, 0, 0);
}
}
void CInPlaceDateTime::PostNcDestroy()
{
CDateTimeCtrl::PostNcDestroy();
delete this;
}
BEGIN_MESSAGE_MAP(CInPlaceDateTime, CDateTimeCtrl)
//{{AFX_MSG_MAP(CInPlaceDateTime)
ON_WM_KILLFOCUS()
ON_WM_KEYDOWN()
ON_WM_KEYUP()
ON_WM_GETDLGCODE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CInPlaceDateTime message handlers
void CInPlaceDateTime::OnKillFocus(CWnd* pNewWnd)
{
CDateTimeCtrl::OnKillFocus(pNewWnd);
if (GetSafeHwnd() == pNewWnd->GetSafeHwnd()) {
return;
}
EndEdit();
}
UINT CInPlaceDateTime::OnGetDlgCode()
{
return DLGC_WANTALLKEYS;
}
void CInPlaceDateTime::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if (( nChar == VK_PRIOR || nChar == VK_NEXT ||
nChar == VK_DOWN || nChar == VK_UP ||
nChar == VK_RIGHT || nChar == VK_LEFT) &&
(m_bExitOnArrows || GetKeyState(VK_CONTROL) < 0))
{
m_nLastChar = nChar;
GetParent()->SetFocus();
return;
}
CDateTimeCtrl::OnKeyDown(nChar, nRepCnt, nFlags);
}
void CInPlaceDateTime::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if (nChar == VK_TAB || nChar == VK_RETURN || nChar == VK_ESCAPE)
{
m_nLastChar = nChar;
GetParent()->SetFocus(); // This will destroy this window
return;
}
CDateTimeCtrl::OnKeyUp(nChar, nRepCnt, nFlags);
}

View File

@@ -0,0 +1,91 @@
// GridCellDateTime.h: interface for the CGridCellDateTime class.
//
// Provides the implementation for a datetime picker cell type of the
// grid control.
//
// For use with CGridCtrl v2.22+
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_DATETIMECELL_H__A0B7DA0A_0AFE_4D28_A00E_846C96D7507A__INCLUDED_)
#define AFX_DATETIMECELL_H__A0B7DA0A_0AFE_4D28_A00E_846C96D7507A__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "../GridCtrl_src/GridCell.h"
#include "afxdtctl.h" // for CDateTimeCtrl
class AFX_EXT_CLASS CGridCellDateTime : public CGridCell
{
friend class CGridCtrl;
DECLARE_DYNCREATE(CGridCellDateTime)
CTime m_cTime;
DWORD m_dwStyle;
public:
CGridCellDateTime();
CGridCellDateTime(DWORD dwStyle);
virtual ~CGridCellDateTime();
// editing cells
public:
void Init(DWORD dwStyle);
virtual BOOL Edit(int nRow, int nCol, CRect rect, CPoint point, UINT nID, UINT nChar);
virtual CWnd* GetEditWnd() const;
virtual void EndEdit();
CTime* GetTime() {return &m_cTime;};
void SetTime(CTime time);
};
class AFX_EXT_CLASS CInPlaceDateTime : public CDateTimeCtrl
{
// Construction
public:
CInPlaceDateTime(CWnd* pParent, // parent
CRect& rect, // dimensions & location
DWORD dwStyle, // window/combobox style
UINT nID, // control ID
int nRow, int nColumn, // row and column
COLORREF crFore, COLORREF crBack, // Foreground, background colour
CTime* pcTime,
UINT nFirstChar); // first character to pass to control
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CInPlaceList)
protected:
virtual void PostNcDestroy();
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CInPlaceDateTime();
void EndEdit();
// Generated message map functions
protected:
//{{AFX_MSG(CInPlaceList)
afx_msg void OnKillFocus(CWnd* pNewWnd);
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg UINT OnGetDlgCode();
//}}AFX_MSG
//afx_msg void OnSelendOK();
DECLARE_MESSAGE_MAP()
private:
CTime* m_pcTime;
int m_nRow;
int m_nCol;
UINT m_nLastChar;
BOOL m_bExitOnArrows;
COLORREF m_crForeClr, m_crBackClr;
};
#endif // !defined(AFX_DATETIMECELL_H__A0B7DA0A_0AFE_4D28_A00E_846C96D7507A__INCLUDED_)

View File

@@ -0,0 +1,42 @@
// GridCellNumeric.cpp: implementation of the CGridCellNumeric class.
//
// Written by Andrew Truckle [ajtruckle@wsatkins.co.uk]
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "GridCellNumeric.h"
#include "../GridCtrl_src/inplaceedit.h"
#include "../GridCtrl_src/GridCtrl.h"
IMPLEMENT_DYNCREATE(CGridCellNumeric, CGridCell)
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
// Create a control to do the editing
BOOL CGridCellNumeric::Edit(int nRow, int nCol, CRect rect, CPoint /* point */, UINT nID, UINT nChar)
{
m_bEditing = TRUE;
// CInPlaceEdit auto-deletes itself
m_pEditWnd = new CInPlaceEdit(GetGrid(), rect, /*GetStyle() |*/ ES_NUMBER, nID, nRow, nCol,
GetText(), nChar);
return TRUE;
}
// Cancel the editing.
void CGridCellNumeric::EndEdit()
{
if (m_pEditWnd)
((CInPlaceEdit*)m_pEditWnd)->EndEdit();
}

View File

@@ -0,0 +1,26 @@
// GridCellNumeric.h: interface for the CGridCellNumeric class.
//
// Written by Andrew Truckle [ajtruckle@wsatkins.co.uk]
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_GRIDINTEGERCELL_H__3479ED0D_B57D_4940_B83D_9E2296ED75B5__INCLUDED_)
#define AFX_GRIDINTEGERCELL_H__3479ED0D_B57D_4940_B83D_9E2296ED75B5__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "../GridCtrl_src/GridCell.h"
class AFX_EXT_CLASS CGridCellNumeric : public CGridCell
{
DECLARE_DYNCREATE(CGridCellNumeric)
public:
virtual BOOL Edit(int nRow, int nCol, CRect rect, CPoint point, UINT nID, UINT nChar);
virtual void EndEdit();
};
#endif // !defined(AFX_GRIDINTEGERCELL_H__3479ED0D_B57D_4940_B83D_9E2296ED75B5__INCLUDED_)

View File

@@ -0,0 +1,206 @@
// GridURLCell.cpp: implementation of the CGridURLCell class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "GridURLCell.h"
#include "../GridCtrl_src/GridCtrl.h"
IMPLEMENT_DYNCREATE(CGridURLCell, CGridCell)
#ifndef _WIN32_WCE
HCURSOR CGridURLCell::g_hLinkCursor = NULL;
#endif
// Possible prefixes that indicate a hyperlink
URLStruct CGridURLCell::g_szURIprefixes[] = {
{ _T("www."), _tcslen(_T("www.")) },
{ _T("http:"), _tcslen(_T("http:")) },
{ _T("mailto:"), _tcslen(_T("mailto:")) },
{ _T("ftp:"), _tcslen(_T("ftp:")) },
{ _T("https:"), _tcslen(_T("https:")) },
{ _T("news:"), _tcslen(_T("news:")) },
{ _T("gopher:"), _tcslen(_T("gopher:")) },
{ _T("telnet:"), _tcslen(_T("telnet:")) },
{ _T("url:"), _tcslen(_T("url:")) },
{ _T("file:"), _tcslen(_T("file:")) },
{ _T("ftp."), _tcslen(_T("ftp.")) }
};
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CGridURLCell::CGridURLCell()
{
#ifndef _WIN32_WCE
g_hLinkCursor = GetHandCursor();
#endif
m_bLaunchUrl = TRUE;
m_clrUrl = GetSysColor(COLOR_HIGHLIGHT);
}
CGridURLCell::~CGridURLCell()
{
}
BOOL CGridURLCell::Draw(CDC* pDC, int nRow, int nCol, CRect rect, BOOL bEraseBkgnd)
{
// If url is present then change text color
if (HasUrl(GetText()))
SetTextClr(m_clrUrl);
// Good a place as any to store the bounds of the rect
m_Rect = rect;
return CGridCell::Draw(pDC, nRow, nCol, rect, bEraseBkgnd);
}
#pragma warning(disable:4100)
BOOL CGridURLCell::Edit(int nRow, int nCol, CRect rect, CPoint point, UINT nID, UINT nChar)
{
return FALSE;
}
#pragma warning(default:4100)
void CGridURLCell::OnClick(CPoint PointCellRelative)
{
#ifndef _WIN32_WCE
CString strURL;
if (GetAutoLaunchUrl() && OverURL(PointCellRelative, strURL))
ShellExecute(NULL, _T("open"), strURL, NULL,NULL, SW_SHOW);
#endif
}
// Return TRUE if you set the cursor
BOOL CGridURLCell::OnSetCursor()
{
#ifndef _WIN32_WCE
CString strURL;
CPoint pt(GetMessagePos());
GetGrid()->ScreenToClient(&pt);
pt = pt - m_Rect.TopLeft();
if (OverURL(pt, strURL))
{
SetCursor(g_hLinkCursor);
return TRUE;
}
else
#endif
return CGridCell::OnSetCursor();
}
#ifndef _WIN32_WCE
HCURSOR CGridURLCell::GetHandCursor()
{
if (g_hLinkCursor == NULL) // No cursor handle - load our own
{
// Get the windows directory
CString strWndDir;
GetWindowsDirectory(strWndDir.GetBuffer(MAX_PATH), MAX_PATH);
strWndDir.ReleaseBuffer();
strWndDir += _T("\\winhlp32.exe");
// This retrieves cursor #106 from winhlp32.exe, which is a hand pointer
HMODULE hModule = LoadLibrary(strWndDir);
if( hModule )
{
HCURSOR hHandCursor = ::LoadCursor(hModule, MAKEINTRESOURCE(106));
if( hHandCursor )
{
g_hLinkCursor = CopyCursor(hHandCursor);
}
}
FreeLibrary(hModule);
}
return g_hLinkCursor;
}
#endif
////////////////////////////////////////////////////////////////////////////////////////////
// Helper functions
BOOL CGridURLCell::HasUrl(CString str)
{
int nNumPrefixes = sizeof(g_szURIprefixes) / sizeof(g_szURIprefixes[0]);
for (int i = 0; i < nNumPrefixes; i++)
//if (str.Left(g_szURIprefixes[i].nLength) == g_szURIprefixes[i].szURLPrefix)
if (str.Find(g_szURIprefixes[i].szURLPrefix) >= 0)
return TRUE;
return FALSE;
}
// here we figure out if we are over a URL or not
BOOL CGridURLCell::OverURL(CPoint& pt, CString& strURL)
{
//TRACE2("Checking point %d,%d\n",pt.x,pt.y);
BOOL bOverURL = FALSE;
CSize size = GetTextExtent(GetText());
// Add left of cell so we know if we clicked on text or not
pt.x += m_Rect.left;
CPoint center = m_Rect.CenterPoint();
if ((m_nFormat & DT_RIGHT) && pt.x >= (m_Rect.right - size.cx))
{
bOverURL = TRUE;
}
else if ((m_nFormat & DT_CENTER) &&
((center.x - (size.cx/2)) <= pt.x) && (pt.x <= (center.x + (size.cx/2))) )
{
bOverURL = TRUE;
}
else if (pt.x <= (size.cx + m_Rect.left))
{
bOverURL = TRUE;
}
if (!bOverURL)
return FALSE;
// We are over text - but are we over a URL?
bOverURL = FALSE;
strURL = GetText();
// Use float, otherwise we get an incorrect letter from the point
float width = (float)size.cx/(float)strURL.GetLength();
// remove left of cell so we have original point again
pt.x -= m_Rect.left;
if (m_nFormat & DT_RIGHT)
{
int wide = m_Rect.Width() - size.cx;
pt.x -= wide;
if (pt.x <= 0)
return FALSE;
}
if (m_nFormat & DT_CENTER)
{
int wide = m_Rect.Width() - size.cx;
pt.x -= (wide/2);
if (pt.x <= 0 || pt.x > (size.cx + (wide/2)))
return FALSE;
}
// Turn point into a letter
int ltrs = (int)((float)pt.x/width);
#if !defined(_WIN32_WCE) || (_WIN32_WCE > 210)
// Find spaces before and after letter, process text between
int endSpace = strURL.Find(_T(' '), ltrs);
if (endSpace != -1)
strURL.Delete(endSpace, strURL.GetLength()-endSpace);
int beginSpace = strURL.ReverseFind(_T(' '));
if (beginSpace != -1)
strURL.Delete(0, ++beginSpace);
#endif
// Does text have url
return HasUrl(strURL);
}

View File

@@ -0,0 +1,55 @@
// GridURLCell.h: interface for the CGridURLCell class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_GRIDURLCELL_H__9F4A50B4_D773_11D3_A439_F7E60631F563__INCLUDED_)
#define AFX_GRIDURLCELL_H__9F4A50B4_D773_11D3_A439_F7E60631F563__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "../GridCtrl_src/GridCell.h"
typedef struct {
LPCTSTR szURLPrefix;
int nLength;
} URLStruct;
class AFX_EXT_CLASS CGridURLCell : public CGridCell
{
DECLARE_DYNCREATE(CGridURLCell)
public:
CGridURLCell();
virtual ~CGridURLCell();
virtual BOOL Draw(CDC* pDC, int nRow, int nCol, CRect rect, BOOL bEraseBkgnd = TRUE);
virtual BOOL Edit(int nRow, int nCol, CRect rect, CPoint point, UINT nID, UINT nChar);
virtual LPCTSTR GetTipText() { return NULL; }
void SetAutoLaunchUrl(BOOL bLaunch = TRUE) { m_bLaunchUrl = bLaunch; }
BOOL GetAutoLaunchUrl() { return m_bLaunchUrl; }
protected:
virtual BOOL OnSetCursor();
virtual void OnClick(CPoint PointCellRelative);
BOOL HasUrl(CString str);
BOOL OverURL(CPoint& pt, CString& strURL);
protected:
#ifndef _WIN32_WCE
static HCURSOR g_hLinkCursor; // Hyperlink mouse cursor
HCURSOR GetHandCursor();
#endif
static URLStruct g_szURIprefixes[];
protected:
COLORREF m_clrUrl;
BOOL m_bLaunchUrl;
CRect m_Rect;
};
#endif // !defined(AFX_GRIDURLCELL_H__9F4A50B4_D773_11D3_A439_F7E60631F563__INCLUDED_)

View File

@@ -0,0 +1,38 @@
========================================================================
정적 라이브러리 : GridControl 프로젝트 개요
========================================================================
응용 프로그램 마법사에서 이 GridControl 라이브러리 프로젝트를 만들었습니다.
이 파일에는 GridControl 응용 프로그램을 구성하는 각각의 파일에
들어 있는 요약 설명이 포함되어 있습니다.
GridControl.vcproj
응용 프로그램 마법사를 사용하여 생성한 VC++ 프로젝트의 기본 프로젝트 파일입니다.
해당 파일을 생성한 Visual C++의 버전 정보를 비롯하여
응용 프로그램 마법사에서 선택한 플랫폼, 구성 및
프로젝트 기능에 대한 정보가 들어 있습니다.
/////////////////////////////////////////////////////////////////////////////
StdAfx.h 및 StdAfx.cpp는
GridControl.pch라는 이름의 PCH(미리 컴파일된 헤더) 파일과
StdAfx.obj라는 이름의 미리 컴파일된 형식 파일을 빌드하는 데 사용됩니다.
/////////////////////////////////////////////////////////////////////////////
컴파일러와 링커 스위치가 MFC를 지원할 수 있도록 변경되었습니다.
MFC 클래스 마법사를 이 프로젝트와 함께 사용하려면 "resource.h",
"GridControl.rc", 그리고 resource.h가 들어 있는 "GridControl.h" 등
몇몇 파일을 해당 프로젝트에 추가해야 합니다.
Dll 또는 Exe는 rc 파일을 하나씩만 포함할 수 있으므로
정적 라이브러리에 rc 파일을 추가하면 문제가 생길 수 있습니다.
그러한 경우 해당 라이브러리의 .rc 파일을 부모 프로젝트의 .rc 파일에 포함시키면 문제가 해결됩니다.
/////////////////////////////////////////////////////////////////////////////
기타 참고:
응용 프로그램 마법사에서 사용하는 "TODO:" 주석은 사용자가 추가하거나 사용자 지정해야 하는
소스 코드 부분을 나타냅니다.
/////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,8 @@
// stdafx.cpp : 표준 포함 파일만 들어 있는 소스 파일입니다.
// GridControl.pch는 미리 컴파일된 헤더가 됩니다.
// stdafx.obj에는 미리 컴파일된 형식 정보가 포함됩니다.
#include "stdafx.h"
// TODO: 필요한 추가 헤더는
// 이 파일이 아닌 STDAFX.H에서 참조합니다.

View File

@@ -0,0 +1,43 @@
// stdafx.h : 잘 변경되지 않고 자주 사용하는
// 표준 시스템 포함 파일 및 프로젝트 관련 포함 파일이
// 들어 있는 포함 파일입니다.
#pragma once
#ifndef VC_EXTRALEAN
#define VC_EXTRALEAN // Windows 헤더에서 거의 사용되지 않는 내용을 제외시킵니다.
#endif
// 아래 지정된 플랫폼보다 우선하는 플랫폼을 대상으로 하는 경우 다음 정의를 수정하십시오.
// 다른 플랫폼에 사용되는 해당 값의 최신 정보는 MSDN을 참조하십시오.
#ifndef WINVER // Windows 95 및 Windows NT 4 이후 버전에서만 기능을 사용할 수 있습니다.
#define WINVER 0x0400 // Windows 98과 Windows 2000 이후 버전에 맞도록 적합한 값으로 변경해 주십시오.
#endif
#ifndef _WIN32_WINNT // Windows NT 4 이후 버전에서만 기능을 사용할 수 있습니다.
#define _WIN32_WINNT 0x0400 // Windows 98과 Windows 2000 이후 버전에 맞도록 적합한 값으로 변경해 주십시오.
#endif
#ifndef _WIN32_WINDOWS // Windows 98 이후 버전에서만 기능을 사용할 수 있습니다.
#define _WIN32_WINDOWS 0x0410 // Windows Me 이후 버전에 맞도록 적합한 값으로 변경해 주십시오.
#endif
#ifndef _WIN32_IE // IE 4.0 이후 버전에서만 기능을 사용할 수 있습니다.
#define _WIN32_IE 0x0400 // IE 5.0 이후 버전에 맞도록 적합한 값으로 변경해 주십시오.
#endif
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // 일부 CString 생성자는 명시적으로 선언됩니다.
// MFC의 공통 부분과 무시 가능한 경고 메시지에 대한 숨기기를 해제합니다.
#define _AFX_ALL_WARNINGS
#include <afxwin.h> // MFC 핵심 및 표준 구성 요소
#include <afxext.h> // MFC 익스텐션
#include <afxdisp.h> // MFC 자동화 클래스
#include <afxdtctl.h> // Internet Explorer 4 공용 컨트롤에 대한 MFC 지원
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h> // Windows 공용 컨트롤에 대한 MFC 지원
#endif // _AFX_NO_AFXCMN_SUPPORT
#include <afxdlgs.h>

View File

@@ -0,0 +1,400 @@
// ManageClient.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "resource.h"
#include "ManageClient.h"
#include <shellapi.h>
#include <Thread/Lock.h> // CNamedMutex
#include <Log/ServerLog.h>
#include <Utility/Debug/ExceptionReport.h> // g_CExceptionReport
#include <Utility/Time/Pulse/Pulse.h>
#include <Utility/Setup/ServerSetup.h>
#include <Network/Session/CreatePolicy.h>
#include <Network/Session/Session.h>
#include <Network/IOCP/IOCPNet.h>
#include <Network/Dispatch/ManageClient/ManageClientDispatch.h>
#include <Network/Packet/ManagePacketCmd.h>
#include <Network/Dispatch/SendManagePacket.h>
#include <Setup/SetupClient.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
CNamedMutex Mutex("ManageClient", TRUE);
if(GetLastError() == ERROR_ALREADY_EXISTS)
{
ERRLOG0(g_Log, "ManageClient already server operating now. please shutdown and restart");
return 0;
}
unsigned long dwExceptionFeatures = CExceptionReport::CATCH_EXCEPTION |
CExceptionReport::USE_MINIDUMP | CExceptionReport::USE_REPORT;
CExceptionReport::GetInstance().Enable(dwExceptionFeatures);
CManageClient& ManageClient = CManageClient::GetInstance();
if(ManageClient.Initialize(hInstance,
CServerSetup::GetInstance().GetManageClientWindowName(),
lpCmdLine, IDI_MANAGECLIENT, IDC_MANAGECLIENT))
{
ManageClient.ProcessMessage();
}
return 0;
}
class CManageClientProcessThread : public CProcessThread
{
public:
enum Const
{
PROCESS_TPP = 200, // 200ms(0.2초) 에 1틱.
CONNECT_CHECK = 10 * (1000 / PROCESS_TPP), // 10초마다 연결 체크
PRINT_CHECK = 2 * (1000 / PROCESS_TPP), // 2초마다 콘솔 출력
PROCESS_CHECK = 3 * (1000 / PROCESS_TPP) // 5초마다 처리 갱신
};
CManageClientProcessThread(CManageClient& ManageClient)
: CProcessThread(ManageClient, PROCESS_TPP),
m_ManageClient(ManageClient)
{
}
private:
virtual void Cleanup(CPulse& Pulse)
{
}
virtual void InternalRun(CPulse& Pulse)
{
unsigned long dwCurrentPulse = Pulse.GetCurrentPulse();
if(0 == (dwCurrentPulse % CONNECT_CHECK))
{
m_ManageClient.CheckConnectionAndReconnect();
}
if(0 == (dwCurrentPulse % PRINT_CHECK))
{
m_ManageClient.PrintConnectionStatus();
}
if(0 == (dwCurrentPulse % PROCESS_CHECK))
{
GET_SINGLE_DISPATCH(lpManageClientDispatch,
CManageClientDispatch, CManageClientDispatch::GetDispatchTable());
if(0 != lpManageClientDispatch)
{
lpManageClientDispatch->CheckProcessStatus();
}
}
}
CManageClient& m_ManageClient;
};
CManageClient& CManageClient::GetInstance()
{
static CManageClient manageClient;
return manageClient;
}
CManageClient::CManageClient()
: m_lpClientSessionPolicy(SessionPolicy::CreateTCPPolicy<CManageClientDispatch>())
{
}
CManageClient::~CManageClient()
{
if(0 != m_lpClientSessionPolicy)
{
m_lpClientSessionPolicy->Release();
m_lpClientSessionPolicy = 0;
}
}
void CManageClient::CheckConnectionAndReconnect()
{
bool bReconnect = false;
GET_SINGLE_DISPATCH(lpManageClientDispatch,
CManageClientDispatch, CManageClientDispatch::GetDispatchTable());
if(0 == lpManageClientDispatch)
{
// 연결이 안 되어 있으면 연결을 테스트함.
CIOCPNet* lpIOCP = GetIOCPNet();
if(0 != lpIOCP)
{
ConnectToManageServer();
}
}
else if(lpManageClientDispatch->DoPatchNow())
{
// 패치를 전부 받고, 패치하기 직전이다. 패치 프로세스를 시작한다.
DoSelfPatchProcess(*lpManageClientDispatch);
}
}
void CManageClient::ConnectToManageServer()
{
CIOCPNet* lpIOCP = GetIOCPNet();
if(0 != lpIOCP && 0 != m_lpClientSessionPolicy)
{
INET_Addr& manageServerAddr = ManageSetup::ClientSetup::GetInstance().GetManageServerAddr();
if(!lpIOCP->Connect(m_lpClientSessionPolicy, manageServerAddr.get_addr_string(),
manageServerAddr.get_port_in()))
{
DETLOG3(g_Log, "this:0x%p/IP:%15s/Port/%02d/ManageServer connect failed.",
this, manageServerAddr.get_addr_string(), manageServerAddr.get_port_in());
}
}
}
void CManageClient::DoSelfPatchProcess(CManageClientDispatch& ClientDispatch)
{
/*
// temporary .bat file
static const TCHAR szTempBatContent[] =
_T(":Repeat\r\n")
_T("del \"%s\"\r\n") // execute file name(full path)
_T("if exist \"%s\" goto Repeat\r\n") // execute file name(full path)
_T(":Repeat2\r\n")
_T("rename %s %s\r\n") // first - temp file name(full path), second - execute file name only
_T("if not exist \"%s\" goto Repeat\r\n") // execute file name(full path)
_T("cd %s\r\n") // execute file path(full path)
_T("%s\r\n"); // execute file name(full path)
static const TCHAR szTempBatName[] = "_manageclient_selfpatch.bat" ;
TCHAR szFullPathModuleName[MAX_PATH]; // absolute path of calling .exe file
TCHAR szModulePath[MAX_PATH]; // Module path
TCHAR szModuleFileName[MAX_PATH]; // fileName
TCHAR szModuleExtension[NAX_PATH]; // extension
TCHAR szTempBatPathName[MAX_PATH]; // absolute path of temporary .bat file
memset(szFullPathModuleName, 0, sizeof(TCHAR) * MAX_PATH);
memset(szModulePath, 0, sizeof(TCHAR) * MAX_PATH);
memset(szTempBatPathName, 0, sizeof(TCHAR) * MAX_PATH);
bool bFailedGetName = true;
unsigned long dwPathLength = GetTempPath(MAX_PATH, szTempBatPathName);
if(0 < dwPathLength)
{
if(0 < _sntprintf(szTempBatPathName + dwPathLength, MAX_PATH - dwPathLength - 1,
"%s", szTempBatName))
{
szTempBatPathName[MAX_PATH - 1] = 0;
bFailedGetName = false;
}
}
const TCHAR* szErrorMessage = 0;
if(bFailedGetName)
{
szErrorMessage = _T("this:0x%p/Failed get tempbat file.");
}
else
{
dwPathLength = GetModuleFileName(NULL, szFullPathModuleName, MAX_PATH - 1);
szFullPathModuleName[MAX_PATH - 1] = 0;
_tsplitpath(szFullPathModuleName, 0, 0, szModuleFileName, szModuleExtension);
_sntprintf(szModuleFileName, szModuleExtension
szModuleFileName = _tcsrchr(szFullPathModuleName, _T('\\'));
if(0 == szModuleFileName)
{
szModuleFileName = _tcsrchr(szFullPathModuleName, _T('/'));
}
if(0 == szModuleFileName || 0 == dwPathLength)
{
szErrorMessage = _T("this:0x%p/Failed get module name.");
}
else
{
memcpy(szModulePath, szFullPathModuleName,
szModuleFileName - szFullPathModuleName);
szModulePath[szModuleFileName - szFullPathModuleName] = _T('\0');
++szModuleFileName;
HANDLE hBatFile = CreateFile(szTempBatPathName, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) ;
if (INVALID_HANDLE_VALUE == hBatFile)
{
szErrorMessage = _T("this:0x%p/Temp bat file create failed.");
}
else
{
DWORD dwLength = 0;
unsigned long dwTempBatContentLen = _tcslen(szTempBatContent);
unsigned long dwFullPathModuleNameLen = _tcslen(szFullPathModuleName);
unsigned long dwTempPathFileLen = _tcslen(ClientDispatch.GetTempPatchFileName());
unsigned long dwModuleFileNameLen = _tcslen(szModuleFileName);
unsigned long dwModulePathLen = _tcslen(szModulePath);
TCHAR* szBatBuffer = new TCHAR[dwTempBatContentLen +
dwFullPathModuleNameLen * 4 +
dwTempPathFileLen +
dwModuleFileNameLen +
dwModulePathLen +
MAX_PATH];
int nLength = _sntprintf(szBatBuffer, MAX_PATH * 10 - 1, szTempBatContent,
szFullPathModuleName, // 지울 파일 이름
szFullPathModuleName, // 파일 존재 여부 체크
ClientDispatch.GetTempPatchFileName(), // 임시 파일 이름
szModuleFileName, // 바뀔 이름
szFullPathModuleName, // 바뀐 이름
szModulePath, // 경로 이동
szFullPathModuleName); // 실행
if(0 < nLength)
{
if(!WriteFile(hBatFile, szBatBuffer, _tcslen(szBatBuffer), &dwLength, NULL))
{
szErrorMessage = _T("this:0x%p/Temp bat file write content failed.");
}
}
else
{
szErrorMessage = _T("this:0x%p/Temp bat file make content failed.");
}
CloseHandle(hBatFile);
delete [] szBatBuffer;
ShellExecute(NULL, _T("open"), szTempBatContent, NULL, NULL, SW_HIDE);
}
}
}
if(0 != szErrorMessage)
{
ERRLOG1(g_Log, szErrorMessage, this);
}
else
{
// 패치 성공. 종료.
DETLOG1(g_Log, "this:0x%p/Patch success. restart now.", this);
PostMessage(GetWnd(), WM_DESTROY, 0, 0);
}
*/
}
bool CManageClient::ApplicationSpecificInit(const TCHAR* szCmdLine)
{
const TCHAR* szErrorMessage = 0;
if(!InitializeMsgProc())
{
szErrorMessage = _T("this:0x%p/InitializeMsgProc failed");
}
else if(!InitializeCommand())
{
szErrorMessage = _T("this:0x%p/InitializeCommand failed");
}
else if(!AddProcessThread(new CManageClientProcessThread(*this)))
{
szErrorMessage = "this:0x%p/AddProcessThread failed";
}
if(0 != szErrorMessage)
{
ERRLOG1(g_Log, szErrorMessage, this);
return false;
}
CheckConnectionAndReconnect();
return true;
}
void CManageClient::PrintConnectionStatus()
{
const int MAX_BUFFER = 4096;
char szBuffer[MAX_BUFFER];
char szFileName[MAX_PATH];
char szExtension[MAX_PATH];
INET_Addr& manageServerAddr = ManageSetup::ClientSetup::GetInstance().GetManageServerAddr();
GET_SINGLE_DISPATCH(lpManageClientDispatch,
CManageClientDispatch, CManageClientDispatch::GetDispatchTable());
int nLength = _snprintf(szBuffer, MAX_BUFFER - 1,
"ManageClient Console\r\n\r\nManageServer IP:%s, Port:%d %s\r\n\r\n",
manageServerAddr.get_addr_string(),
manageServerAddr.get_port_in(),
(0 != lpManageClientDispatch) ? "Connected" : "Disconnected");
int nTotalLength = 0;
if(0 < nLength)
{
if(0 != lpManageClientDispatch)
{
nTotalLength += nLength;
CManageClientDispatch::RunTable& runTable = lpManageClientDispatch->GetRunTable();
CManageClientDispatch::RunTable::iterator pos = runTable.begin();
CManageClientDispatch::RunTable::iterator end = runTable.end();
for(; pos != end; ++pos)
{
const ServerManage::RunInfo& runInfo = pos->second.m_RunInfo;
_splitpath(runInfo.m_szPath, 0, 0, szFileName, szExtension);
nLength = _snprintf(szBuffer + nTotalLength, MAX_BUFFER - nTotalLength,
"RunID:%5d / %s%s %s\r\n",
runInfo.m_dwRunID, szFileName, szExtension, runInfo.m_szOption);
if(0 < nLength)
{
nTotalLength += nLength;
}
}
}
if(0 < nTotalLength && nTotalLength < MAX_BUFFER)
{
szBuffer[nTotalLength] = 0;
PrintInfo(szBuffer);
}
}
}

View File

@@ -0,0 +1,35 @@
#ifndef _RYL_GM_NETWORK_MANAGE_CLIENT_H_
#define _RYL_GM_NETWORK_MANAGE_CLIENT_H_
#include <Utility/ServerAppFramework/ServerWindowFramework.h>
// forward decl.
class CSessionPolicy;
class CManageClientDispatch;
class CManageClient : public CServerWindowFramework
{
public:
static CManageClient& GetInstance();
void CheckConnectionAndReconnect();
void ConnectToManageServer();
void DoSelfPatchProcess(CManageClientDispatch& ClientDispatch);
void PrintConnectionStatus();
private:
CManageClient();
virtual ~CManageClient();
virtual bool ApplicationSpecificInit(const TCHAR* szCmdLine);
bool InitializeMsgProc();
bool InitializeCommand();
CSessionPolicy* m_lpClientSessionPolicy;
};
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@@ -0,0 +1,97 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#define APSTUDIO_HIDDEN_SYMBOLS
#include "windows.h"
#undef APSTUDIO_HIDDEN_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// Çѱ¹¾î resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_KOR)
#ifdef _WIN32
LANGUAGE LANG_KOREAN, SUBLANG_DEFAULT
#pragma code_page(949)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_SMALL ICON "small.ico"
IDI_MANAGECLIENT ICON "ManageClient.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
IDC_MANAGECLIENT MENU
BEGIN
POPUP "ManageClient"
BEGIN
MENUITEM "Open Console(&O)", ID_MANAGECLIENT_OPEN_CONSOLE
MENUITEM "Close Console(&C)", ID_MANAGECLIENT_CLOSE_CONSOLE
MENUITEM SEPARATOR
MENUITEM "Reload Setup(&R)", ID_MANAGECLIENT_RELOADSETUP
MENUITEM SEPARATOR
MENUITEM "Exit(&E)", IDM_EXIT
END
END
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
"#include ""windows.h""\r\n"
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // Çѱ¹¾î resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@@ -0,0 +1,176 @@
<?xml version="1.0" encoding="ks_c_5601-1987"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="ManageClient"
ProjectGUID="{1B7E2874-2F79-4399-ABA5-512ABF1120F6}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../Executable/$(ConfigurationName)"
IntermediateDirectory="../Intermediate/$(ProjectName)/$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="./;../;../../RylServerProject/BaseLibrary;../../RylServerProject/RylServerLibrary;../ManageLibrary"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="2"
WarningLevel="3"
Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/ManageClient.exe"
LinkIncremental="2"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/ManageClient.pdb"
SubSystem="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../Executable/$(ConfigurationName)"
IntermediateDirectory="../Intermediate/$(ProjectName)/$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="./;../;../../RylServerProject/BaseLibrary;../../RylServerProject/RylServerLibrary;../ManageLibrary"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
RuntimeLibrary="0"
UsePrecompiledHeader="2"
WarningLevel="3"
Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/ManageClient.exe"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="소스 파일"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath=".\ManageClient.cpp">
</File>
<File
RelativePath=".\ManageClientCommand.cpp">
</File>
<File
RelativePath=".\ManageClientMsg.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=".\ManageClient.h">
</File>
<File
RelativePath=".\Resource.h">
</File>
<File
RelativePath=".\stdafx.h">
</File>
</Filter>
<Filter
Name="리소스 파일"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
<File
RelativePath=".\ManageClient.ico">
</File>
<File
RelativePath=".\ManageClient.rc">
</File>
<File
RelativePath=".\small.ico">
</File>
</Filter>
<File
RelativePath=".\ReadMe.txt">
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,63 @@
#include "stdafx.h"
#include "ManageClient.h"
#include <Log/ServerLog.h>
#include <Setup/SetupClient.h>
#include <Utility/ServerAppFrameWork/ConsoleWindow/ConsoleCMDFactory.h>
#include <Network/Session/Session.h>
#include <Network/Dispatch/ManageClient/ManageClientDispatch.h>
class CCMDPrintLog : public CConsoleCMDSingleton<CCMDPrintLog>
{
protected:
virtual bool DoProcess()
{
SERLOG0(g_Log, "Flush log.");
SERLOG0(g_SessionLog, "Flush log");
return true;
}
};
class CCMDReloadSetup : public CConsoleCMDSingleton<CCMDReloadSetup>
{
protected:
virtual bool DoProcess()
{
ManageSetup::ClientSetup::GetInstance().Load();
GET_SINGLE_DISPATCH(lpManageClientDispatch,
CManageClientDispatch, CManageClientDispatch::GetDispatchTable());
if(0 != lpManageClientDispatch)
{
// 연결을 끊은 후 재접속을 시도한다.
lpManageClientDispatch->GetSession().Shutdown();
}
return true;
}
};
bool CManageClient::InitializeCommand()
{
#define INIT_COMMAND_FAILED(detail) TEXT("Command create failed - "##detail)
#define ADD_COMMAND(cmdstring, cmdobject, errmsg_val) \
if(0 == (errmsg_val) && !GetCommandFactory()->AddCommand(cmdstring, new cmdobject)) { \
(errmsg_val) = INIT_COMMAND_FAILED(cmdstring); }
const TCHAR* szErrorMessage = 0;
ADD_COMMAND("flush", CCMDPrintLog, szErrorMessage);
ADD_COMMAND("reload", CCMDReloadSetup, szErrorMessage);
if(0 != szErrorMessage)
{
ERRLOG0(g_Log, szErrorMessage);
return false;
};
return true;
}

View File

@@ -0,0 +1,120 @@
#include "stdafx.h"
#include "Resource.h"
#include "ManageClient.h"
#include <Utility/ServerAppFramework/MsgProc/MsgProc.h>
#include <Utility/ServerAppFramework/ConsoleWindow/ConsoleWindow.h>
#include <Utility/ServerAppFramework/ConsoleWindow/ConsoleCMDFactory.h>
#include <Network/Dispatch/ManageClient/ManageClientDispatch.h>
#include <Network/Dispatch/SendManagePacket.h>
#include <Log/ServerLog.h>
class CIPCMessage : public CMsgProc
{
private:
virtual LRESULT operator () (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
GET_SINGLE_DISPATCH(lpManageClientDispatch,
CManageClientDispatch, CManageClientDispatch::GetDispatchTable());
if(0 != lpManageClientDispatch && 0 != lParam)
{
// µ¥ÀÌÅÍ ¸Þ½ÃÁö.
COPYDATASTRUCT& copyDataStruct = *reinterpret_cast<PCOPYDATASTRUCT>(lParam);
ServerManage::PktManagePacket* lpPktManage =
reinterpret_cast<ServerManage::PktManagePacket*>(copyDataStruct.lpData);
ServerManage::PktManagePing* lpPktManagePing =
static_cast<ServerManage::PktManagePing*>(lpPktManage);
unsigned long dwRunID = 0;
if(ServerManage::CMD::IPC_ManagePing == lpPktManage->GetCmd()
&& copyDataStruct.cbData == sizeof(ServerManage::PktManagePing)
&& lpManageClientDispatch->GetRunIDFromString(
lpPktManagePing->m_szAppFullPathName, lpPktManagePing->m_szCommandLine, dwRunID))
{
HWND hWnd = FindWindow(lpPktManagePing->m_szWindowName,
lpPktManagePing->m_szWindowName);
if(0 != hWnd)
{
lpManageClientDispatch->SetAppData(dwRunID,
hWnd, lpPktManage->m_dwPID, lpPktManagePing->m_dwStatusFlag);
}
}
else if(lpManageClientDispatch->GetRunIDFromPID(lpPktManage->m_dwPID, dwRunID))
{
ServerManage::SendManagePacket(lpManageClientDispatch->GetSession(),
ServerManage::CMD::RelayCommand, WM_COPYDATA, wParam, 0, dwRunID,
static_cast<unsigned short>(copyDataStruct.cbData), 0, copyDataStruct.lpData, 0);
}
}
return 0;
}
};
class CProcessCommandMessage : public CMsgProc
{
public:
CProcessCommandMessage(CManageClient& ManageClient) : m_ManageClient(ManageClient) { }
private:
virtual LRESULT operator () (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
char* szCommand = 0;
CConsoleWindow* lpConsoleWindow = m_ManageClient.GetConsoleWindow();
if(0 == lpConsoleWindow)
{
return 0;
}
switch (LOWORD(wParam))
{
case ID_MANAGECLIENT_OPEN_CONSOLE: lpConsoleWindow->Initialize("ROWManageClient"); break;
case ID_MANAGECLIENT_CLOSE_CONSOLE: lpConsoleWindow->Destroy(); break;
case ID_MANAGECLIENT_RELOADSETUP: szCommand = "reload"; break;
}
if(0 != szCommand)
{
lpConsoleWindow->GetCMDProcess().Add(
lpConsoleWindow->GetConsoleCMDFactory().Create(szCommand, strlen(szCommand)));
}
if(LOWORD(wParam) == IDM_EXIT)
{
DETLOG0(g_Log, "Terminate ManageServer System Tray.");
PostMessage(hWnd, WM_QUIT, 0, 0);
}
return 0;
}
CManageClient& m_ManageClient;
};
bool CManageClient::InitializeMsgProc()
{
CMsgProcessMgr* lpMsgProcessMgr = GetMsgProcessMgr();
if(0 == lpMsgProcessMgr)
{
return false;
}
int nErrorCount = 0;
lpMsgProcessMgr->Remove(WM_COPYDATA);
nErrorCount += lpMsgProcessMgr->Register(WM_COPYDATA, new CIPCMessage) ? 0 : 1;
nErrorCount += lpMsgProcessMgr->Register(WM_COMMAND, new CProcessCommandMessage(*this)) ? 0 : 1;
return 0 == nErrorCount;
}

View File

@@ -0,0 +1,53 @@
========================================================================
Win32 응용 프로그램 : ManageClient 프로젝트 개요
========================================================================
응용 프로그램 마법사에서 이 ManageClient 응용 프로그램을 만들었습니다.
이 파일에는 ManageClient 응용 프로그램을 구성하는 각각의 파일에
들어 있는 요약 설명이 포함되어 있습니다.
ManageClient.vcproj
응용 프로그램 마법사를 사용하여 생성한 VC++ 프로젝트의 기본 프로젝트 파일입니다.
해당 파일을 생성한 Visual C++의 버전 정보를 비롯하여
응용 프로그램 마법사에서 선택한 플랫폼, 구성 및
프로젝트 기능에 대한 정보가 들어 있습니다.
ManageClient.cpp
기본 응용 프로그램 소스 파일입니다.
/////////////////////////////////////////////////////////////////////////////
응용 프로그램 마법사에서 다음 리소스를 만들었습니다.
ManageClient.rc
프로그램에서 사용하는 모든
Microsoft Windows 리소스의 목록입니다. RES 하위 디렉터리에 저장된
아이콘, 비트맵, 및 커서 등이 여기에 포함됩니다. 이 파일은
Microsoft Visual C++에서 직접 편집할 수 있습니다.
Resource.h
새 리소스 ID를 정의하는 표준 헤더 파일입니다.
Microsoft Visual C++에서 이 파일을 읽고 업데이트합니다.
ManageClient.ico
아이콘 파일이며, 응용 프로그램의 아이콘(32x32)으로 사용됩니다.
해당 아이콘은 기본 리소스 파일인 ManageClient.rc에 의해 포함됩니다.
small.ico
아이콘 파일이며, 응용 프로그램 아이콘의 더 작은 버전(16x16)이
들어 있습니다. 해당 아이콘은 기본 리소스 파일인
ManageClient.rc에 의해 포함됩니다.
/////////////////////////////////////////////////////////////////////////////
기타 표준 파일:
StdAfx.h 및 StdAfx.cpp는
ManageClient.pch라는 이름의 PCH(미리 컴파일된 헤더) 파일과
StdAfx.obj라는 이름의 미리 컴파일된 형식 파일을 빌드하는 데 사용됩니다.
/////////////////////////////////////////////////////////////////////////////
기타 참고:
응용 프로그램 마법사에서 사용하는 "TODO:" 주석은 사용자가 추가하거나 사용자 지정해야 하는
소스 코드 부분을 나타냅니다.
/////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,30 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by ManageClient.rc
//
#define IDC_MYICON 2
#define IDD_MANAGECLIENT_DIALOG 102
#define IDS_APP_TITLE 103
#define IDM_ABOUT 104
#define IDM_EXIT 105
#define IDI_SMALL 108
#define IDC_MANAGECLIENT 109
#define IDR_MAINFRAME 128
#define IDI_ICON1 129
#define IDI_MANAGECLIENT 129
#define ID_MANAGECLIENT_RELOADSETUP 32771
#define ID_MANAGECLIENT_CLOSE_CONSOLE 32774
#define ID_MANAGECLIENT_OPEN_CONSOLE 32775
#define IDC_STATIC -1
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 130
#define _APS_NEXT_COMMAND_VALUE 32776
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 110
#endif
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -0,0 +1,8 @@
// stdafx.cpp : 표준 포함 파일만 들어 있는 소스 파일입니다.
// ManageClient.pch는 미리 컴파일된 헤더가 됩니다.
// stdafx.obj에는 미리 컴파일된 형식 정보가 포함됩니다.
#include "stdafx.h"
// TODO: 필요한 추가 헤더는
// 이 파일이 아닌 STDAFX.H에서 참조합니다.

View File

@@ -0,0 +1,18 @@
// stdafx.h : 자주 사용하지만 자주 변경되지는 않는
// 표준 시스템 포함 파일 및 프로젝트 관련 포함 파일이
// 들어 있는 포함 파일입니다.
//
#pragma once
#define WIN32_LEAN_AND_MEAN // 거의 사용되지 않는 내용은 Windows 헤더에서 제외합니다.
// Windows 헤더 파일입니다.
#include <windows.h>
// C의 런타임 헤더 파일입니다.
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
// TODO: 프로그램에 필요한 추가 헤더는 여기에서 참조합니다.

View File

@@ -0,0 +1,84 @@
#include "stdafx.h"
#include "SQLite.h"
#include "ManageServerDB.h"
#include <Log/ServerLog.h>
#include <cstdio>
const char* CManageServerDB::GetDefaultDBFileName()
{
return "./ManageServerDB.dat";
}
CManageServerDB& CManageServerDB::GetInstance()
{
static CManageServerDB manageServerDB;
return manageServerDB;
}
CManageServerDB::CManageServerDB()
: m_lpSQLite(new CSQLite)
{
}
CManageServerDB::~CManageServerDB()
{
if(0 != m_lpSQLite)
{
delete m_lpSQLite;
m_lpSQLite = 0;
}
}
bool CManageServerDB::Initialize(const char* szDBFileName)
{
if(0 == m_lpSQLite || !m_lpSQLite->Open(szDBFileName))
{
ERRLOG1(g_Log, "Cannot open database : %s", szDBFileName);
return false;
}
// Create Tables - 이미 만들어져 있으면 에러가 난다.
const int MAX_QUERY_NUM = 5;
const char* szCreateTableQuery[MAX_QUERY_NUM] =
{
"CREATE TABLE TblManageToolUser (ID char(16) PRIMARY KEY, PASS char(16), "
"NAME char(32), IP char(16), LEVEL INTEGER)",
"CREATE TABLE TblServerInfo (IP INTEGER PRIMARY KEY, ServerName char(64))",
"CREATE TABLE TblRunPath (PathID INTEGER PRIMARY KEY, RunPath char(260))",
"CREATE TABLE TblRunOptions (OptionID INTEGER PRIMARY KEY, RunOption char(260))",
"CREATE TABLE TblRunInfo (RunID INTEGER PRIMARY KEY, PathID INTEGER, OptionID INTEGER, ServerIP INTEGER)"
};
m_lpSQLite->SetErrorLog(false);
for(int nQuery = 0; nQuery < MAX_QUERY_NUM; ++nQuery)
{
CSQLite::Dataset createUserTable(*m_lpSQLite, szCreateTableQuery[nQuery]);
if(!createUserTable.Compile() || !createUserTable.Execute())
{
if(0 != createUserTable.GetLastError())
{
// Table create failed. if already create failed?
char szTableName[MAX_PATH];
int nLength = sscanf(createUserTable.GetLastError(), "table %s already exists", szTableName);
if(EOF == nLength || 0 == nLength)
{
m_lpSQLite->SetErrorLog(true);
return false;
}
}
}
}
m_lpSQLite->SetErrorLog(true);
return true;
}

View File

@@ -0,0 +1,24 @@
#ifndef _MANAGE_SERVER_TOOL_DB_FILE_DB_LIB_SQL_LITE_
#define _MANAGE_SERVER_TOOL_DB_FILE_DB_LIB_SQL_LITE_
class CSQLite;
class CManageServerDB
{
public:
static const char* GetDefaultDBFileName();
static CManageServerDB& GetInstance();
bool Initialize(const char* szDBFileName = CManageServerDB::GetDefaultDBFileName());
CSQLite& GetSQLite() { return *m_lpSQLite; }
private:
CManageServerDB();
~CManageServerDB();
CSQLite* m_lpSQLite;
};
#endif

View File

@@ -0,0 +1,220 @@
#include "stdafx.h"
#include "SQLite.h"
#include <cstdlib>
#include <sqlite-library/sqlite.h>
#include <Log/ServerLog.h>
#define SAFE_FREE_SQLITE_ERRMSG(p) if(p) { sqlite_freemem(p); (p) = 0; }
CSQLite::CSQLite()
: m_sqlDB(0), m_szErrorMsg(0), m_bLogError(true)
{
}
CSQLite::~CSQLite()
{
SAFE_FREE_SQLITE_ERRMSG(m_szErrorMsg);
Close();
}
bool CSQLite::Open(const char* szDBFileName)
{
char* szErrMsg = 0;
m_sqlDB = sqlite_open(szDBFileName, 0, &szErrMsg);
if(0 == m_sqlDB)
{
if(m_bLogError)
{
ERRLOG2(g_Log, "Can't open database : %s(%d)",
szDBFileName, GetLastError());
}
SAFE_FREE_SQLITE_ERRMSG(m_szErrorMsg);
m_szErrorMsg = szErrMsg;
return false;
}
return true;
}
void CSQLite::Close()
{
if(0 != m_sqlDB)
{
sqlite_close(m_sqlDB);
}
}
int CSQLite::GetLastInsertRowID()
{
return sqlite_last_insert_rowid(m_sqlDB);
}
bool CSQLite::ExecuteQuery(const char* szQuery, QueryCallBack fnCallBack, void* callBackArg)
{
char* szErrorMsg = 0;
int nResult = sqlite_exec(m_sqlDB, szQuery, fnCallBack, callBackArg, &szErrorMsg);
if(SQLITE_OK != nResult)
{
if(m_bLogError)
{
ERRLOG2(g_Log, "Execute Query failed : %s(Query:%s)",
szErrorMsg, szQuery);
}
SAFE_FREE_SQLITE_ERRMSG(m_szErrorMsg);
m_szErrorMsg = szErrorMsg;
return false;
}
return true;
}
CSQLite::Dataset::Dataset(CSQLite& sqlite, const char* szQuery)
: m_SQLite(sqlite),
m_sqlite_vm(0),
m_szQuery(szQuery),
m_szErrorMsg(0),
m_nExecuteResult(SQLITE_ROW)
{
}
CSQLite::Dataset::~Dataset()
{
Free();
SAFE_FREE_SQLITE_ERRMSG(m_szErrorMsg);
}
bool CSQLite::Dataset::Compile()
{
Free();
const char* szNextQuery = 0;
char* szErrorMsg = 0;
if('\0' == *m_szQuery)
{
// 쿼리가 끝까지 완료되었으면 빠져나감.
return false;
}
int nResult = sqlite_compile(m_SQLite.GetHandle(), m_szQuery,
&szNextQuery, &m_sqlite_vm, &szErrorMsg);
if(SQLITE_OK != nResult)
{
if(m_SQLite.IsErrorLogging())
{
ERRLOG2(g_Log, "SQLite error : compile query error - %s(%d)",
szErrorMsg, GetLastError());
}
SAFE_FREE_SQLITE_ERRMSG(m_szErrorMsg);
m_szErrorMsg = szErrorMsg;
return false;
}
m_szQuery = szNextQuery;
return true;
}
bool CSQLite::Dataset::Execute(int* nColNum_Out,
const char *** pazValue,
const char *** pazColName)
{
m_nExecuteResult = sqlite_step(m_sqlite_vm, nColNum_Out, pazValue, pazColName);
if(SQLITE_ROW == m_nExecuteResult ||
SQLITE_DONE == m_nExecuteResult)
{
return true;
}
else
{
if(m_SQLite.IsErrorLogging())
{
ERRLOG1(g_Log, "SQLite error : Dataset - execute error :%s",
sqlite_error_string(m_nExecuteResult));
}
}
return false;
}
bool CSQLite::Dataset::IsExcuteDone()
{
return (SQLITE_ROW != m_nExecuteResult);
}
void CSQLite::Dataset::Free()
{
if(0 != m_sqlite_vm)
{
char* szErrorMsg = 0;
if(SQLITE_OK != sqlite_finalize(m_sqlite_vm, &szErrorMsg))
{
if(m_SQLite.IsErrorLogging())
{
ERRLOG2(g_Log, "SQLite error : finalize error - %s(%d)",
szErrorMsg, GetLastError());
}
SAFE_FREE_SQLITE_ERRMSG(m_szErrorMsg);
m_szErrorMsg = szErrorMsg;
}
m_sqlite_vm = 0;
}
}
CSQLite::Tableset::Tableset(CSQLite& sqlite, const char* szQuery)
: m_SQLite(sqlite), m_szQuery(szQuery), m_nRow(0), m_nCol(0),
m_szResult(0), m_szErrorMsg(0)
{
}
CSQLite::Tableset::~Tableset()
{
if(0 != m_szResult)
{
sqlite_free_table(m_szResult);
m_szResult = 0;
}
}
bool CSQLite::Tableset::Execute()
{
char* szErrorMsg = 0;
if(SQLITE_OK != sqlite_get_table(m_SQLite.GetHandle(), m_szQuery,
&m_szResult, &m_nRow, &m_nCol, &szErrorMsg))
{
if(m_SQLite.IsErrorLogging())
{
ERRLOG2(g_Log, "SQLite error : get_table error - %s(%d)",
szErrorMsg, GetLastError());
}
SAFE_FREE_SQLITE_ERRMSG(m_szErrorMsg);
m_szErrorMsg = szErrorMsg;
return false;
}
return true;
}

View File

@@ -0,0 +1,93 @@
#ifndef _MANAGE_TOOL_DB_FILE_DB_LIB_SQL_LITE_
#define _MANAGE_TOOL_DB_FILE_DB_LIB_SQL_LITE_
// forward decl;
typedef struct sqlite_vm sqlite_vm;
typedef struct sqlite sqlite;
class CSQLite
{
public:
typedef int (*QueryCallBack)(void *callBackArg, int nColumnNum,
char **szColumnValues, char **szColumnNames);
CSQLite();
virtual ~CSQLite();
bool Open(const char* szFileName);
void Close();
int GetLastInsertRowID();
bool ExecuteQuery(const char* szQuery, QueryCallBack callBack, void* callBackArg);
const char* GetLastError() const { return m_szErrorMsg; }
void SetErrorLog(bool bLogError) { m_bLogError = bLogError; }
bool IsErrorLogging() { return m_bLogError; }
class Dataset
{
public:
Dataset(CSQLite& sqlite, const char* szQuery);
~Dataset();
// 쿼리를 컴파일해서 처리 준비를 한다.
bool Compile();
// 쿼리를 실행하고 결과를 얻어온다.
bool Execute(int* nColNum_Out = 0,
const char ***pazValue = 0,
const char *** pazColName = 0);
bool IsExcuteDone();
const char* GetLastError() const { return m_szErrorMsg; }
void Free();
private:
CSQLite& m_SQLite;
sqlite_vm* m_sqlite_vm;
const char* m_szQuery;
char* m_szErrorMsg;
int m_nExecuteResult;
};
class Tableset
{
public:
Tableset(CSQLite& sqlite, const char* szQuery);
~Tableset();
bool Execute();
char** GetResult() { return m_szResult; }
int GetMaxRow() { return m_nRow; }
int GetMaxCol() { return m_nCol; }
const char* GetLastError() const { return m_szErrorMsg; }
private:
CSQLite& m_SQLite;
const char* m_szQuery;
char** m_szResult;
int m_nRow;
int m_nCol;
char* m_szErrorMsg;
};
private:
sqlite* GetHandle() { return m_sqlDB; }
sqlite* m_sqlDB;
char* m_szErrorMsg;
bool m_bLogError;
friend class Dataset;
friend class Tableset;
};
#endif

View File

@@ -0,0 +1,232 @@
<?xml version="1.0" encoding="ks_c_5601-1987"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="ManageLibrary"
ProjectGUID="{9E56BA4B-AEF8-4F86-9B17-50647A98AE64}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../Library/$(ConfigurationName)"
IntermediateDirectory="../Intermediate/$(ProjectName)/$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="./;../;../../RylServerProject/BaseLibrary;../../RylServerProject/RylServerLibrary"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="2"
WarningLevel="3"
Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/ManageLibrary.lib"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../Library/$(ConfigurationName)"
IntermediateDirectory="../Intermediate/$(ProjectName)/$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="./;../;../../RylServerProject/BaseLibrary;../../RylServerProject/RylServerLibrary"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
RuntimeLibrary="0"
UsePrecompiledHeader="2"
WarningLevel="3"
Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/ManageLibrary.lib"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Network"
Filter="">
<Filter
Name="Dispatch"
Filter="">
<File
RelativePath=".\Network\Dispatch\SendManagePacket.cpp">
</File>
<File
RelativePath=".\Network\Dispatch\SendManagePacket.h">
</File>
<Filter
Name="ManageClient"
Filter="">
<File
RelativePath=".\Network\Dispatch\ManageClient\ManageClientDispatch.cpp">
</File>
<File
RelativePath=".\Network\Dispatch\ManageClient\ManageClientDispatch.h">
</File>
</Filter>
<Filter
Name="ManageServer"
Filter="">
<File
RelativePath=".\Network\Dispatch\ManageServer\ManageServerDispatch.cpp">
</File>
<File
RelativePath=".\Network\Dispatch\ManageServer\ManageServerDispatch.h">
</File>
<File
RelativePath=".\Network\Dispatch\ManageServer\ManageToolServerDispatch.cpp">
</File>
<File
RelativePath=".\Network\Dispatch\ManageServer\ManageToolServerDispatch.h">
</File>
<File
RelativePath=".\Network\Dispatch\ManageServer\ParseUserManage.cpp">
</File>
<File
RelativePath=".\Network\Dispatch\ManageServer\StatServerDispatch.cpp">
</File>
<File
RelativePath=".\Network\Dispatch\ManageServer\StatServerDispatch.h">
</File>
<File
RelativePath=".\Network\Dispatch\ManageServer\StatServerMultiDispatch.cpp">
</File>
<File
RelativePath=".\Network\Dispatch\ManageServer\StatServerMultiDispatch.h">
</File>
</Filter>
</Filter>
</Filter>
<Filter
Name="UserManage"
Filter="">
<File
RelativePath=".\UserManage\ToolUserManageTable.cpp">
</File>
<File
RelativePath=".\UserManage\ToolUserManageTable.h">
</File>
<File
RelativePath=".\UserManage\UserStatistics.cpp">
</File>
<File
RelativePath=".\UserManage\UserStatistics.h">
</File>
</Filter>
<Filter
Name="ServerManage"
Filter="">
<File
RelativePath=".\ServerManage\ManageClientManager.cpp">
</File>
<File
RelativePath=".\ServerManage\ManageClientManager.h">
</File>
<File
RelativePath=".\ServerManage\SendManageInfo.cpp">
</File>
</Filter>
<Filter
Name="DB"
Filter="">
<File
RelativePath=".\Db\ManageServerDB.cpp">
</File>
<File
RelativePath=".\Db\ManageServerDB.h">
</File>
<File
RelativePath=".\Db\SQLite.cpp">
</File>
<File
RelativePath=".\Db\SQLite.h">
</File>
</Filter>
<Filter
Name="Setup"
Filter="">
<File
RelativePath=".\Setup\RylServerBindRunID.cpp">
</File>
<File
RelativePath=".\Setup\RylServerBindRunID.h">
</File>
<File
RelativePath=".\Setup\RylServerGroupSetup.cpp">
</File>
<File
RelativePath=".\Setup\RylServerGroupSetup.h">
</File>
<File
RelativePath=".\Setup\SetupClient.cpp">
</File>
<File
RelativePath=".\Setup\SetupClient.h">
</File>
</Filter>
<File
RelativePath=".\ReadMe.txt">
</File>
<File
RelativePath=".\stdafx.cpp">
</File>
<File
RelativePath=".\stdafx.h">
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,835 @@
#include "stdafx.h"
#include "ManageClientDispatch.h"
#include <Network/Session/Session.h>
#include <Network/Packet/ManagePacketCmd.h>
#include <Setup/SetupClient.h>
#include <Network/Dispatch/SingleDispatchStorage.h>
#include <Network/Dispatch/SendManagePacket.h>
#include <Log/ServerLog.h>
#include <tlhelp32.h>
#include <mmsystem.h>
#include <string>
#include <vector>
#pragma comment(lib, "winmm.lib")
/*
// forward decl
HANDLE GetProcessHandle(const char* szProcessFullPathName, unsigned long* lpdwPID);
*/
enum ManageClientConst
{
MANAGE_CLIENT_DEFAULT_DISPATCH_NUM = 10
};
CManageClientDispatch::RunExtraInfo::RunExtraInfo(const ServerManage::RunInfo& runInfo,
HANDLE hProcess, unsigned long dwProcessID)
: m_RunInfo(runInfo), m_hProcess(hProcess), m_dwProcessID(dwProcessID),
m_hWnd(0), m_dwCustomStatus(0), m_dwLastSetWindowHandleTime(0)
{
char szCommand[MAX_PATH];
_snprintf(szCommand, MAX_PATH - 1, "%s", m_RunInfo.m_szOption);
szCommand[MAX_PATH - 1] = 0;
char* szData = strtok(szCommand, " \t\r\n");
while(0 != szData)
{
m_CommandSet.insert(szData);
szData = strtok(0, " \t\r\n");
}
}
CSingleDispatch& CManageClientDispatch::GetDispatchTable()
{
static CSingleDispatch singleDispatch;
return singleDispatch;
}
CManageClientDispatch::CManageClientDispatch(CSession& Session)
: CRylServerDispatch(Session, MANAGE_CLIENT_DEFAULT_DISPATCH_NUM),
m_hPatchFile(INVALID_HANDLE_VALUE),
m_bDoPatchNow(false)
{
TCHAR* szTempFileName = _T("./mytmp_patch.tmp");
memset(m_szTempPatchFileName, 0, sizeof(TCHAR) * MAX_PATH);
_tcscpy(m_szTempPatchFileName, szTempFileName);
TCHAR szFullPathModuleName[MAX_PATH];
GetModuleFileName(NULL, szFullPathModuleName, MAX_PATH - 1);
szFullPathModuleName[MAX_PATH - 1] = 0;
TCHAR szDrive[MAX_PATH];
TCHAR szPath[MAX_PATH];
TCHAR szName[MAX_PATH];
TCHAR szExtension[MAX_PATH];
_tsplitpath(szFullPathModuleName, szDrive, szPath, szName, szExtension);
_sntprintf(m_szTempPatchFileName, MAX_PATH - 1,
_T("%s\\%s\\%s"), szDrive, szPath, szTempFileName);
m_szTempPatchFileName[MAX_PATH - 1] = 0;
DETLOG1(g_Log, "this:0x%p/CManageClientDispatch Created", this);
}
CManageClientDispatch::~CManageClientDispatch()
{
if(INVALID_HANDLE_VALUE != m_hPatchFile)
{
// 파일이 아직 열려 있다. 닫는다.
ERRLOG2(g_Log, "this:0x%0p/HANDLE:0x%p/PatchFile is not closed. close now", this, m_hPatchFile);
CloseHandle(m_hPatchFile);
}
DETLOG1(g_Log, "this:0x%p/CManageClientDispatch Destroyed", this);
}
void CManageClientDispatch::Connected()
{
GetDispatchTable().SetDispatch(this);
DETLOG1(g_Log, "this:0x%p/CManageClientDispatch Connected", this);
}
void CManageClientDispatch::Disconnected()
{
GetDispatchTable().RemoveDispatch(this);
DETLOG1(g_Log, "this:0x%p/CManageClientDispatch Disconnected", this);
}
bool CManageClientDispatch::DispatchPacket(PktBase* lpPktBase)
{
PktBase::LengthType nPacketLen = lpPktBase->GetLen();
if(nPacketLen < sizeof(ServerManage::ManageCommand))
{
ERRLOG3(g_Log, "IP:%15s/PacketLen:%d/Cmd:0x%02x/Invalid packet length or command",
GetSession().GetRemoteAddr().get_addr_string(), lpPktBase->GetLen(), lpPktBase->GetCmd());
}
else
{
ServerManage::ManageCommand* lpManageCommand =
reinterpret_cast<ServerManage::ManageCommand*>(lpPktBase);
if(nPacketLen != sizeof(ServerManage::ManageCommand) + lpManageCommand->usDataLen)
{
ERRLOG3(g_Log, "IP:%15s/PacketLen:%d/Cmd:0x%02x/Invalid packet length",
GetSession().GetRemoteAddr().get_addr_string(), lpPktBase->GetLen(), lpPktBase->GetCmd());
}
else
{
TCHAR* szWindowName = 0;
char* lpData = (0 != lpManageCommand->usDataLen) ?
reinterpret_cast<char*>(lpManageCommand + 1) : 0;
const TCHAR* szErrorMessage = 0;
switch(lpManageCommand->GetCmd())
{
case ServerManage::CMD::UpdateRunList: // 실행 목룍을 준다 (ManageServer -> ManageClient, ManageTool), Ack없음.
ProcessUpdateRunList(lpData, lpManageCommand->usDataLen, lpManageCommand->usFlags);
break;
case ServerManage::CMD::RunProcess: // 실행한다. (ManageTool -> ManageServer -> ManageClient), Ack는 반대 순서로 전송
ProcessRunServer(lpManageCommand->dwRunID);
break;
case ServerManage::CMD::QuitProcess: // 종료한다. (ManageTool -> ManageServer -> ManageClient), Ack는 반대 순성로 전송
ProcessQuitServer(lpManageCommand->dwRunID);
break;
case ServerManage::CMD::ForceTerminate: // 강제 종료한다. (ManageTool -> ManageServer -> ManageClient), Ack는 반대 순서로 전송
ProcessTerminateServer(lpManageCommand->dwRunID);
break;
case ServerManage::CMD::RelayCommand: // 패킷 커맨드를 윈도우 메시지를 써서 중계해서 넘긴다.
/*
if(!ProcessRelayCommand(lpManageCommand->nMessage,
lpManageCommand->wParam, lpManageCommand->lParam,
szWindowName, lpData, lpManageCommand->usDataLen, lpManageCommand->cFlag))
{
szErrorMessage = _T("RelayCommand : RelayCommand Failed");
}
*/
break;
case ServerManage::CMD::AutoPatch: // 자기 자신을 패치한다
if(!ProcessAutoPatch(lpData, lpManageCommand->usDataLen, lpManageCommand->usFlags))
{
szErrorMessage = _T("AutoPatch : AutoPatch packet process failed");
}
break;
case ServerManage::CMD::ChangeSetup: // 설정을 바꾸고 저장한다.
if(!ManageSetup::ClientSetup::GetInstance().SerializeIn(lpData, lpManageCommand->usDataLen))
{
szErrorMessage = _T("ChangeSetup : Change setup failed");
}
else
{
ManageSetup::ClientSetup::GetInstance().Save();
}
break;
case ServerManage::CMD::ReloadSetup: // 설정을 재로드한다.
ManageSetup::ClientSetup::GetInstance().Load();
break;
case ServerManage::CMD::ExecuteCommand:
ProcessExecuteConsoleCommand(lpManageCommand);
break;
default:
szErrorMessage = _T("Unknown message : Process failed");
break;
}
if(0 != szErrorMessage)
{
ERRLOG4(g_Log, "IP:%15s/DetailCmd:0x%02x/Error:%d/%s",
GetSession().GetRemoteAddr().get_addr_string(),
lpPktBase->GetCmd(), GetLastError(), szErrorMessage);
}
}
}
return true;
}
bool CManageClientDispatch::ProcessRelayCommand(unsigned int nMessage, WPARAM wParam, LPARAM lParam,
const char* szWindowName, const char* lpData,
unsigned short usDataLen, unsigned char cFlag)
{
if(0 != szWindowName)
{
HWND hWnd = FindWindow(0, szWindowName);
if(0 != hWnd)
{
if(0 != lpData && WM_COPYDATA == nMessage)
{
COPYDATASTRUCT copyDataStruct;
copyDataStruct.dwData = 0;
copyDataStruct.cbData = usDataLen;
copyDataStruct.lpData = (void*)lpData;
// 메시지를 보낸다.
SendMessage(hWnd, nMessage, wParam,
reinterpret_cast<LPARAM>(&copyDataStruct));
}
else
{
SendMessage(hWnd, nMessage, wParam, lParam);
}
}
}
return true;
}
bool CManageClientDispatch::ProcessAutoPatch(const char* lpData, unsigned short usDataLen, unsigned short usFlag)
{
switch(usFlag)
{
case ServerManage::ManageCommand::AUTOPATCH_OPENFILE:
if(INVALID_HANDLE_VALUE != m_hPatchFile)
{
// 패치 파일이 열려 있음. 닫는다.
ERRLOG2(g_Log, "this:0x%0p/HANDLE:0x%p/PatchFile is not closed. close now for create new one",
this, m_hPatchFile);
CloseHandle(m_hPatchFile);
}
// 파일을 생성한다.
m_hPatchFile = CreateFile(m_szTempPatchFileName, GENERIC_WRITE, 0, 0,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if(INVALID_HANDLE_VALUE == m_hPatchFile)
{
ERRLOG2(g_Log, "this:0x%p/Error:%d/Patch tempfile create failed",
this, GetLastError());
}
break;
case ServerManage::ManageCommand::AUTOPATCH_DATA:
if(INVALID_HANDLE_VALUE != m_hPatchFile)
{
unsigned long dwWritten = 0;
unsigned long dwTotalWritten = 0;
while(usDataLen != dwTotalWritten)
{
if(!WriteFile(m_hPatchFile, lpData, usDataLen, &dwWritten, 0))
{
ERRLOG3(g_Log, "this:0x%p/HANDLE:0x%p/Error:%d/Patchfile write failed.",
this, m_hPatchFile, GetLastError());
CloseHandle(m_hPatchFile);
m_hPatchFile = INVALID_HANDLE_VALUE;
DeleteFile(m_szTempPatchFileName);
break;
}
dwTotalWritten += dwWritten;
}
if(0 == usDataLen && INVALID_HANDLE_VALUE != m_hPatchFile)
{
// 파일을 전부 받았다. 이제 전송을 종료하고 패치를 적용한다.
m_bDoPatchNow = true;
}
}
else
{
ERRLOG1(g_Log, "this:0x%p/Patchfile is invalid", this);
}
break;
}
return true;
}
bool CManageClientDispatch::ProcessUpdateRunList(const char* szData, unsigned short usDataLen,
unsigned short usFlags)
{
if(ServerManage::SEND_RUNINFO_START == usFlags)
{
// 기존에 열었던 Process들에 대해서 전부 핸들을 닫는다.
RunTable::iterator pos = m_RunTable.begin();
RunTable::iterator end = m_RunTable.end();
for(; pos != end; ++pos)
{
RunExtraInfo& runExtraInfo = pos->second;
if(0 != runExtraInfo.m_hProcess)
{
CloseHandle(runExtraInfo.m_hProcess);
}
}
m_RunTable.clear();
}
else if(ServerManage::SEND_RUNINFO_NOW == usFlags)
{
// RunTable에 세팅하고, 프로세스를 연다.
const ServerManage::RunInfo* lpRunInfo = reinterpret_cast<const ServerManage::RunInfo*>(szData);
const ServerManage::RunInfo* lpEndRunInfo = lpRunInfo + (usDataLen / sizeof(ServerManage::RunInfo));
for(; lpRunInfo != lpEndRunInfo; ++lpRunInfo)
{
m_RunTable.insert(RunTable::value_type(lpRunInfo->m_dwRunID,
RunExtraInfo(*lpRunInfo, 0, 0)));
}
}
else if(ServerManage::SEND_RUNINFO_FINISH == usFlags)
{
// 프로세스 상태 갱신 패킷을 보낸다.
CheckProcessStatus();
}
return true;
}
bool CManageClientDispatch::ProcessRunServer(unsigned long dwRunID)
{
RunTable::iterator pos = m_RunTable.find(dwRunID);
if(pos != m_RunTable.end())
{
RunExtraInfo& runExInfo = pos->second;
TCHAR szDrive[MAX_PATH];
TCHAR szPath[MAX_PATH];
TCHAR szDefaultPath[MAX_PATH];
_splitpath(runExInfo.m_RunInfo.m_szPath, szDrive, szPath, 0, 0);
_snprintf(szDefaultPath, MAX_PATH - 1, "%s%s", szDrive, szPath);
szDefaultPath[MAX_PATH - 1] = 0;
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
// Start the child process.
/*
if(CreateProcess(runExInfo.m_RunInfo.m_szPath, runExInfo.m_RunInfo.m_szOption, 0, 0,
FALSE, 0, 0, szDefaultPath, &si, &pi))
*/
char szExecutePath[MAX_PATH * 2];
_snprintf(szExecutePath, MAX_PATH * 2 - 1, "\"%s\" %s",
runExInfo.m_RunInfo.m_szPath, runExInfo.m_RunInfo.m_szOption);
szExecutePath[MAX_PATH * 2 - 1] = 0;
if(CreateProcess(0, szExecutePath, 0, 0,
FALSE, 0, 0, szDefaultPath, &si, &pi))
{
runExInfo.m_hProcess = pi.hProcess;
runExInfo.m_dwProcessID = pi.dwProcessId;
DETLOG4(g_Log, "Execute file success, RunID(%u), Path(%s), Option(%s), DefaultPath(%s)",
runExInfo.m_RunInfo.m_dwRunID, runExInfo.m_RunInfo.m_szPath,
runExInfo.m_RunInfo.m_szOption, szDefaultPath);
}
else
{
ERRLOG5(g_Log, "Cannot execute file : CreateProcess failed(%d), RunID(%u), "
"Path(%s), Option(%s), DefaultPath(%s)",
WSAGetLastError(), runExInfo.m_RunInfo.m_dwRunID,
runExInfo.m_RunInfo.m_szPath, runExInfo.m_RunInfo.m_szOption, szDefaultPath);
}
}
else
{
ERRLOG1(g_Log, "Cannot execute file : Unknown RunID(%d)", dwRunID);
}
return true;
}
bool CManageClientDispatch::ProcessQuitServer(unsigned long dwRunID)
{
RunTable::iterator pos = m_RunTable.find(dwRunID);
if(pos != m_RunTable.end())
{
RunExtraInfo& runExInfo = pos->second;
if(0 != runExInfo.m_hWnd)
{
TCHAR szWindowName[MAX_PATH];
GetWindowText(runExInfo.m_hWnd, szWindowName, MAX_PATH - 1);
szWindowName[MAX_PATH - 1] = 0;
SendMessage(runExInfo.m_hWnd, WM_DESTROY, 0, 0);
DETLOG6(g_Log, "Send quit message : HANDLE(0x%p), PID(0x%08x), WindowName(%s), "
"RunID(%u), Path(%s), Option(%s)",
runExInfo.m_hProcess, runExInfo.m_dwProcessID, szWindowName,
runExInfo.m_RunInfo.m_dwRunID, runExInfo.m_RunInfo.m_szPath,
runExInfo.m_RunInfo.m_szOption);
}
else
{
ERRLOG5(g_Log, "Cannot send quit message (Get window failed) : "
"HANDLE(0x%p), PID(0x%08x), RunID(%u), Path(%s), Option(%s)",
runExInfo.m_hProcess, runExInfo.m_dwProcessID,
runExInfo.m_RunInfo.m_dwRunID, runExInfo.m_RunInfo.m_szPath,
runExInfo.m_RunInfo.m_szOption);
}
}
return true;
}
bool CManageClientDispatch::ProcessTerminateServer(unsigned long dwRunID)
{
RunTable::iterator pos = m_RunTable.find(dwRunID);
if(pos != m_RunTable.end())
{
RunExtraInfo& runExInfo = pos->second;
if(0 != runExInfo.m_hProcess)
{
if(TerminateProcess(runExInfo.m_hProcess, -1))
{
DETLOG5(g_Log, "Terminate process. HANDLE(0x%p), PID(0x%08x), "
"RunID(%u), Path(%s), Option(%s)",
runExInfo.m_hProcess, runExInfo.m_dwProcessID,
runExInfo.m_RunInfo.m_dwRunID, runExInfo.m_RunInfo.m_szPath,
runExInfo.m_RunInfo.m_szOption);
}
else
{
ERRLOG6(g_Log, "Cannot terminate process. Err(%d), HANDLE(0x%p), PID(0x%08x), "
"RunID(%u), Path(%s), Option(%s)",
GetLastError(), runExInfo.m_hProcess, runExInfo.m_dwProcessID,
runExInfo.m_RunInfo.m_dwRunID, runExInfo.m_RunInfo.m_szPath,
runExInfo.m_RunInfo.m_szOption);
}
}
}
return true;
}
bool CManageClientDispatch::ProcessExecuteConsoleCommand(ServerManage::ManageCommand* lpManageCmd)
{
RunTable::iterator pos = m_RunTable.find(lpManageCmd->dwRunID);
if(pos != m_RunTable.end())
{
RunExtraInfo& runExInfo = pos->second;
if(0 != runExInfo.m_hWnd)
{
COPYDATASTRUCT copyDataStruct;
copyDataStruct.dwData = 0;
copyDataStruct.cbData = lpManageCmd->GetLen();
copyDataStruct.lpData = lpManageCmd;
SendMessage(runExInfo.m_hWnd, WM_COPYDATA, 0, (LPARAM)&copyDataStruct);
}
}
return true;
}
void CManageClientDispatch::CheckProcessStatus()
{
const int MAX_PROCESS_STATUS_SEND_ONCE =
(PktMaxLen - sizeof(ServerManage::ManageCommand)) / sizeof(ServerManage::ProcessStatus);
ServerManage::ProcessStatus procesStatus[MAX_PROCESS_STATUS_SEND_ONCE];
RunTable::iterator pos = m_RunTable.begin();
RunTable::iterator end = m_RunTable.end();
for(; pos != end; ++pos)
{
RunExtraInfo& runExtraInfo = pos->second;
// 체크하고, PID가 있는데 프로세스가 열리지 않은 프로그램은, 프로세스를 연다.
if(0 != runExtraInfo.m_dwProcessID && 0 != runExtraInfo.m_hWnd
&& 0 == runExtraInfo.m_hProcess)
{
runExtraInfo.m_hProcess = OpenProcess(PROCESS_ALL_ACCESS,
FALSE, runExtraInfo.m_dwProcessID);
}
}
unsigned long dwExitCode = 0;
unsigned long dwErrorCode = 0;
unsigned short usSendProcessStatus = 0;
pos = m_RunTable.begin();
end = m_RunTable.end();
for(; pos != end; ++pos)
{
RunExtraInfo& runExtraInfo = pos->second;
// Default - Deactivated Process.
ServerManage::ProcessStatus* lpCurrentProcessStatus = procesStatus + usSendProcessStatus;
memset(lpCurrentProcessStatus, 0, sizeof(ServerManage::ProcessStatus));
lpCurrentProcessStatus->m_dwRunID = runExtraInfo.m_RunInfo.m_dwRunID;
lpCurrentProcessStatus->m_dwStatusFlags = 0;
lpCurrentProcessStatus->m_dwCurrentTime = timeGetTime();
lpCurrentProcessStatus->m_dwCustomStatus = runExtraInfo.m_dwCustomStatus;
lpCurrentProcessStatus->m_dwLastSetWindowHandleTime = runExtraInfo.m_dwLastSetWindowHandleTime;
if(0 != runExtraInfo.m_hProcess)
{
GetProcessTimes(runExtraInfo.m_hProcess,
&lpCurrentProcessStatus->m_CreationTIme,
&lpCurrentProcessStatus->m_ExitTime,
&lpCurrentProcessStatus->m_KernelTime,
&lpCurrentProcessStatus->m_UserTime);
GetProcessMemoryInfo(runExtraInfo.m_hProcess,
&lpCurrentProcessStatus->m_ProcessMemoryCounters,
sizeof(PROCESS_MEMORY_COUNTERS));
if(!GetExitCodeProcess(runExtraInfo.m_hProcess, &dwExitCode))
{
ERRLOG3(g_Log, "GetExitCodeProcess failed(%d) : RunID(%u), Path(%s)",
dwErrorCode, runExtraInfo.m_RunInfo.m_dwRunID,
runExtraInfo.m_RunInfo.m_szPath);
}
else if(dwExitCode != STILL_ACTIVE)
{
DETLOG4(g_Log, "Close process handle : HANDLE(0x%p), PID(0x%08x), RunID(%u), Path(%s)",
runExtraInfo.m_hProcess, runExtraInfo.m_dwProcessID,
runExtraInfo.m_RunInfo.m_dwRunID, runExtraInfo.m_RunInfo.m_szPath);
CloseHandle(runExtraInfo.m_hProcess);
runExtraInfo.m_hProcess = 0;
runExtraInfo.m_dwProcessID = 0;
runExtraInfo.m_hWnd = 0;
runExtraInfo.m_dwLastSetWindowHandleTime = 0;
}
else
{
lpCurrentProcessStatus->m_dwStatusFlags =
ServerManage::PROCESS_RUNNING;
}
}
++usSendProcessStatus;
if(usSendProcessStatus == MAX_PROCESS_STATUS_SEND_ONCE)
{
ServerManage::SendManagePacket(GetSession(), ServerManage::CMD::ProcessStatus,
0, 0, 0, 0, sizeof(ServerManage::ProcessStatus) * usSendProcessStatus, 0, procesStatus, 0);
usSendProcessStatus = 0;
}
}
if(0 < usSendProcessStatus)
{
ServerManage::SendManagePacket(GetSession(), ServerManage::CMD::ProcessStatus,
0, 0, 0, 0, sizeof(ServerManage::ProcessStatus) * usSendProcessStatus, 0, procesStatus, 0);
usSendProcessStatus = 0;
}
}
bool CManageClientDispatch::SetAppData(unsigned long dwRunID, HWND hWnd,
unsigned long dwPID, unsigned long dwCustomStatus)
{
RunTable::iterator pos = m_RunTable.find(dwRunID);
RunTable::iterator end = m_RunTable.end();
if(pos != end)
{
RunExtraInfo& runExtraInfo = pos->second;
runExtraInfo.m_dwProcessID = dwPID;
runExtraInfo.m_hWnd = hWnd;
runExtraInfo.m_dwCustomStatus = dwCustomStatus;
runExtraInfo.m_dwLastSetWindowHandleTime = timeGetTime();
return true;
}
return false;
}
bool CManageClientDispatch::GetRunIDFromString(const char* szAppName, const char* szCommandLine,
unsigned long& dwRunID_Out)
{
char szProcessName[MAX_PATH];
char szProcessSnapName[MAX_PATH];
_snprintf(szProcessSnapName, MAX_PATH - 1, "%s", szAppName);
szProcessSnapName[MAX_PATH - 1] = 0;
_strupr(szProcessSnapName);
char szCommandLineData[MAX_PATH * 2];
_snprintf(szCommandLineData, MAX_PATH * 2 - 1, "%s", szCommandLine);
szCommandLineData[MAX_PATH * 2 - 1] = 0;
RunExtraInfo::CommandSet commandSet;
char* szData = 0;
if('\"' == szCommandLineData[0])
{
szData = strtok(szCommandLineData, "\"");
szData = strtok(0, "\"");
if(0 != szData)
{
// 파일명을 분리한 Argument를 받아서 처리..
char szRealCommandLine[MAX_PATH];
_snprintf(szRealCommandLine, MAX_PATH - 1, "%s", szData);
szRealCommandLine[MAX_PATH - 1] = 0;
szData = strtok(szRealCommandLine, " \t\r\n");
while(0 != szData)
{
commandSet.insert(szData);
szData = strtok(0, " \t\r\n");
}
}
}
else
{
szData = strtok(szCommandLineData, " \t\r\n");
// 첫번째 Argument는 파일명이므로 무시.
szData = strtok(0, " \t\r\n");
while(0 != szData)
{
commandSet.insert(szData);
szData = strtok(0, " \t\r\n");
}
}
RunTable::iterator pos = m_RunTable.begin();
RunTable::iterator end = m_RunTable.end();
for(; pos != end; ++pos)
{
RunExtraInfo& runExtraInfo = pos->second;
_snprintf(szProcessName, MAX_PATH - 1, "%s", runExtraInfo.m_RunInfo.m_szPath);
szProcessName[MAX_PATH - 1] = 0;
_strupr(szProcessName);
if(0 == strncmp(szProcessName, szProcessSnapName, MAX_PATH))
{
if((runExtraInfo.m_CommandSet.size() == commandSet.size()
&& std::equal(runExtraInfo.m_CommandSet.begin(),
runExtraInfo.m_CommandSet.end(), commandSet.begin())))
{
dwRunID_Out = runExtraInfo.m_RunInfo.m_dwRunID;
return true;
}
}
}
dwRunID_Out = 0;
return false;
}
bool CManageClientDispatch::GetRunIDFromPID(unsigned long dwPID, unsigned long& dwRunID_Out)
{
RunTable::iterator pos = m_RunTable.begin();
RunTable::iterator end = m_RunTable.end();
for(; pos != end; ++pos)
{
RunExtraInfo& runExtraInfo = pos->second;
if(runExtraInfo.m_dwProcessID == dwPID)
{
dwRunID_Out = runExtraInfo.m_RunInfo.m_dwRunID;
return true;
}
}
dwRunID_Out = 0;
return false;
}
/*
HANDLE GetProcessHandle(const char* szProcessFullPathName, unsigned long* lpdwPID)
{
HANDLE hProcess = INVALID_HANDLE_VALUE;
if(0 == lpdwPID)
{
return hProcess;
}
// Take a snapshot of all processes in the system.
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
{
return hProcess;
}
// Fill in the size of the structure before using it.
PROCESSENTRY32 pe32 = {0};
pe32.dwSize = sizeof(PROCESSENTRY32);
// Walk the snapshot of the processes, and for each process,
// display information.
char szProcessName[MAX_PATH];
char szProcessSnapName[MAX_PATH];
_snprintf(szProcessName, MAX_PATH - 1, "%s", szProcessFullPathName);
szProcessName[MAX_PATH - 1] = 0;
_strupr(szProcessName);
bool bFound = false;
if (Process32First(hProcessSnap, &pe32))
{
do
{
MODULEENTRY32 me32 = {0};
HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pe32.th32ProcessID);
if (hModuleSnap != INVALID_HANDLE_VALUE)
{
me32.dwSize = sizeof(MODULEENTRY32);
if (Module32First(hModuleSnap, &me32))
{
do
{
_snprintf(szProcessSnapName, MAX_PATH - 1, "%s", me32.szExePath);
szProcessSnapName[MAX_PATH - 1] = 0;
_strupr(szProcessSnapName);
if(0 == strcmp(szProcessName, szProcessSnapName))
{
// Get the actual priority class.
hProcess = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);
if(INVALID_HANDLE_VALUE == hProcess)
{
ERRLOG2(g_Log, "Process open failed(%d) : %s",
GetLastError(), me32.szExePath);
}
*lpdwPID = pe32.th32ProcessID;
bFound = true;
break;
}
}
while (!bFound && Module32Next(hModuleSnap, &me32));
}
CloseHandle (hModuleSnap);
}
}
while (!bFound && Process32Next(hProcessSnap, &pe32));
}
CloseHandle(hProcessSnap);
return hProcess;
}
*/

View File

@@ -0,0 +1,90 @@
#ifndef _GM_MANAGE_CLIENT_DISPATCH_H_
#define _GM_MANAGE_CLIENT_DISPATCH_H_
#pragma warning(disable:4800)
#include <map>
#include <set>
#include <boost/pool/pool_alloc.hpp>
#include <Network/Dispatch/RylServerDispatch.h>
#include <Network/Dispatch/SingleDispatchStorage.h>
#include <Network/Packet/ManagePacketCmd.h>
// CManageClientDispatch를 쓰는 클라이언트만 이 라이브러리를 링크함.
#pragma comment(lib, "psapi.lib")
class CManageClientDispatch : public CRylServerDispatch
{
public:
struct RunExtraInfo
{
typedef std::set<std::string> CommandSet;
ServerManage::RunInfo m_RunInfo;
HANDLE m_hProcess;
HWND m_hWnd;
unsigned long m_dwProcessID;
unsigned long m_dwCustomStatus;
unsigned long m_dwLastSetWindowHandleTime;
CommandSet m_CommandSet;
RunExtraInfo();
RunExtraInfo(const ServerManage::RunInfo& runInfo,
HANDLE hProcess, unsigned long dwProcessID);
};
// Key - RunID
typedef std::map<unsigned long, RunExtraInfo, std::less<unsigned long>,
boost::pool_allocator<std::pair<unsigned long, RunExtraInfo> > > RunTable;
static CSingleDispatch& GetDispatchTable();
CManageClientDispatch(CSession& Session);
virtual ~CManageClientDispatch();
void CheckProcessStatus();
bool DoPatchNow() const { return m_bDoPatchNow; }
const TCHAR* GetTempPatchFileName() const { return m_szTempPatchFileName; }
bool SetAppData(unsigned long dwRunID, HWND hWnd,
unsigned long dwPID, unsigned long dwCustomStatus);
bool GetRunIDFromPID(unsigned long dwPID, unsigned long& dwRunID_Out);
bool GetRunIDFromString(const char* szAppName,
const char* szCommandLine, unsigned long& dwRunID_Out);
RunTable& GetRunTable() { return m_RunTable; }
private:
virtual void Connected();
virtual void Disconnected();
virtual bool DispatchPacket(PktBase* lpPktBase);
bool ProcessUpdateRunList(const char* szData, unsigned short usDataLen, unsigned short usFlags);
bool ProcessRunServer(unsigned long dwRunID);
bool ProcessQuitServer(unsigned long dwRunID);
bool ProcessTerminateServer(unsigned long dwRunID);
bool ProcessExecuteConsoleCommand(ServerManage::ManageCommand* lpManageCmd);
bool ProcessRelayCommand(unsigned int nMessage, WPARAM wParam, LPARAM lParam,
const char* szWindowName, const char* lpData, unsigned short usDataLen, unsigned char cFlag);
bool ProcessAutoPatch(const char* lpData, unsigned short usDataLen, unsigned short usFlag);
// Member variable;
HANDLE m_hPatchFile; // 패치 파일 핸들.
TCHAR m_szTempPatchFileName[MAX_PATH]; // 임시 패치 파일 이름.
bool m_bDoPatchNow; // 패치 준비가 되었는지 여부를 알아옴.
RunTable m_RunTable;
};
#endif

View File

@@ -0,0 +1,231 @@
#include "stdafx.h"
#include "ManageServerDispatch.h"
#include "ManageToolServerDispatch.h"
#include <Network/Session/Session.h>
#include <Network/Packet/ManagePacketCmd.h>
#include <Network/Dispatch/SendManagePacket.h>
#include <Network/Dispatch/MultiDispatchStorage.h>
#include <UserManage/ToolUserManageTable.h>
#include <Log/ServerLog.h>
#include <Setup/SetupClient.h>
#include <ServerManage/ManageClientManager.h>
#include <UserManage/UserStatistics.h>
enum ManageServerConst
{
MANAGE_SERVER_DEFAULT_DISPATCH_NUM = 100
};
CMultiDispatch& CManageServerDispatch::GetDispatchTable()
{
static CMultiDispatch multiDispatch;
return multiDispatch;
}
CManageServerDispatch::CManageServerDispatch(CSession& Session)
: CRylServerDispatch(Session, MANAGE_SERVER_DEFAULT_DISPATCH_NUM),
m_bAuthorized(false)
{
memset(&m_UserInfo, 0, sizeof(ServerManage::UserInfo));
DETLOG1(g_Log, "this:0x%p/CManageServerDispatch Created", this);
}
CManageServerDispatch::~CManageServerDispatch()
{
DETLOG1(g_Log, "this:0x%p/CManageServerDispatch Destroyed", this);
}
void CManageServerDispatch::Connected()
{
// 접속 IP를 key로 잡아서 세팅한다.
INET_Addr& remoteAddr = GetSession().GetRemoteAddr();
unsigned long dwDispatchID = remoteAddr.get_addr_in().sin_addr.S_un.S_addr;
GetDispatchTable().SetDispatch(dwDispatchID, this);
// TODO : 서버 IP로 검색해서, RunInfo들을 전송한다.
CManageClientManager::RunTable runInfoTable;
CManageClientManager::GetInstance().GetRunInfoFromIP(dwDispatchID, runInfoTable);
if(!CManageClientManager::SendRunInfo(GetSession(), runInfoTable))
{
ERRLOG3(g_Log, "SS:0x%p/DP:0x%p/IP:%15s/Send runInfo failed",
&GetSession(), this, remoteAddr.get_addr_string());
}
DETLOG2(g_Log, "this:0x%p/Key:%u/CManageServerDispatch Connected", this, dwDispatchID);
}
class CSendProcessData
{
public:
CSendProcessData(ServerManage::ProcessStatus* lpProcessData,
unsigned short usProcessDataNum)
: m_lpProcessData(lpProcessData), m_usProcessDataNum(usProcessDataNum)
{
}
bool operator () (CManageToolServerDispatch& toolDispatch)
{
ServerManage::SendManagePacket(toolDispatch.GetSession(), ServerManage::CMD::ProcessStatus,
0, 0, 0, 0, sizeof(ServerManage::ProcessStatus) * m_usProcessDataNum, 0, m_lpProcessData, 0);
return true;
}
private:
ServerManage::ProcessStatus* m_lpProcessData;
unsigned short m_usProcessDataNum;
};
void CManageServerDispatch::Disconnected()
{
// 접속 IP를 key로 잡아서 세팅한다.
INET_Addr& remoteAddr = GetSession().GetRemoteAddr();
unsigned long dwDispatchID = remoteAddr.get_addr_in().sin_addr.S_un.S_addr;
GetDispatchTable().RemoveDispatch(dwDispatchID);
CManageClientManager::RunTable runInfoTable;
CManageClientManager::GetInstance().GetRunInfoFromIP(dwDispatchID, runInfoTable);
CManageClientManager::RunTable::iterator pos = runInfoTable.begin();
CManageClientManager::RunTable::iterator end = runInfoTable.end();
const int MAX_PROCESS_STATUS_SEND_ONCE =
(PktMaxLen - sizeof(ServerManage::ManageCommand)) / sizeof(ServerManage::ProcessStatus);
ServerManage::ProcessStatus procesStatus[MAX_PROCESS_STATUS_SEND_ONCE];
unsigned short usSendProcessStatus = 0;
for(; pos != end; ++pos)
{
ServerManage::RunInfo& runInfo = pos->second;
// Default - Deactivated Process.
ServerManage::ProcessStatus* lpCurrentProcessStatus = procesStatus + usSendProcessStatus;
memset(lpCurrentProcessStatus, 0, sizeof(ServerManage::ProcessStatus));
lpCurrentProcessStatus->m_dwRunID = runInfo.m_dwRunID;
++usSendProcessStatus;
if(usSendProcessStatus == MAX_PROCESS_STATUS_SEND_ONCE)
{
CToolUserManager::GetInstance().ProcessCurrentUser(
CSendProcessData(procesStatus, usSendProcessStatus));
usSendProcessStatus = 0;
}
}
if(0 < usSendProcessStatus)
{
CToolUserManager::GetInstance().ProcessCurrentUser(
CSendProcessData(procesStatus, usSendProcessStatus));
usSendProcessStatus = 0;
}
DETLOG2(g_Log, "this:0x%p/Key:%u/CManageServerDispatch Disconnected", this, dwDispatchID);
}
bool CManageServerDispatch::DispatchPacket(PktBase* lpPktBase)
{
PktBase::LengthType nPacketLen = lpPktBase->GetLen();
bool bResult = false;
switch(lpPktBase->GetCmd())
{
case ServerManage::CMD::ProcessStatus:
CUserStatistics::GetInstance().CheckClearUser(lpPktBase);
RelayPacketToManageTools(lpPktBase);
break;
case ServerManage::CMD::RelayCommand:
RelayPacketToManageTools(lpPktBase);
break;
default:
{
in_addr addr;
addr.S_un.S_addr = m_UserInfo.dwIP;
ERRLOG4(g_Log, "ID:%s/Name:%s/IP:%s/Cmd:0x%02x/Undefined command.",
m_UserInfo.szID, m_UserInfo.szFullName, inet_ntoa(addr),
lpPktBase->GetCmd());
}
break;
}
return true;
}
bool CManageServerDispatch::RelayPacketToManageTools(PktBase* lpPktBase)
{
unsigned char cError = 0;
bool bDoNotRelay = false;
ServerManage::ManageCommand* lpManageCommand =
reinterpret_cast<ServerManage::ManageCommand*>(lpPktBase);
if(!ServerManage::CheckManagePacketLength(lpPktBase))
{
cError = ServerManage::INVALID_MANAGE_PACKET_ERROR;
}
if(sizeof(ServerManage::PktManagePacket) <= lpManageCommand->usDataLen)
{
ServerManage::PktManagePacket* lpPktManagePacket =
reinterpret_cast<ServerManage::PktManagePacket*>(lpManageCommand + 1);
switch(lpPktManagePacket->m_dwSubCommand)
{
case ServerManage::CMD::SubCmd_ServerUserNum:
{
ServerManage::PktManageUserNum* lpPktManageUserNum =
static_cast<ServerManage::PktManageUserNum*>(lpPktManagePacket);
/*
DETLOG2(g_Log, "RunID:%d/PID:%d/Setting UserInfo",
lpManageCommand->dwRunID, lpPktManageUserNum->m_dwPID);
*/
CUserStatistics::GetInstance().SerializeIn(lpManageCommand->dwRunID,
reinterpret_cast<ServerManage::UserNumPair*>(lpPktManageUserNum + 1),
lpPktManageUserNum->m_dwUserInfoNum);
}
break;
}
}
if(0 == cError && !bDoNotRelay)
{
CToolUserManager::GetInstance().ProcessCurrentUser(
ServerManage::CSendManagePacketToClient(*lpManageCommand,
reinterpret_cast<char*>(lpManageCommand + 1)));
return true;
}
return ServerManage::SendManagePacket(GetSession(),
lpPktBase->GetCmd(), 0, 0, 0, 0, 0, 0, 0, cError);
}

View File

@@ -0,0 +1,30 @@
#ifndef _GM_MANAGE_SERVER_DISPATCH_H_
#define _GM_MANAGE_SERVER_DISPATCH_H_
#include <Network/Packet/ManagePacketCmd.h>
#include <Network/Dispatch/RylServerDispatch.h>
#include <Network/Dispatch/MultiDispatchStorage.h>
class CManageServerDispatch : public CRylServerDispatch
{
public:
static CMultiDispatch& GetDispatchTable();
CManageServerDispatch(CSession& Session);
virtual ~CManageServerDispatch();
private:
virtual void Connected();
virtual void Disconnected();
virtual bool DispatchPacket(PktBase* lpPktBase);
bool RelayPacketToManageTools(PktBase* lpPktBase);
ServerManage::UserInfo m_UserInfo;
bool m_bAuthorized;
};
#endif

View File

@@ -0,0 +1,320 @@
#include "stdafx.h"
#include "ManageServerDispatch.h"
#include "ManageToolServerDispatch.h"
#include <Network/Session/Session.h>
#include <Network/Dispatch/SendManagePacket.h>
#include <Network/Dispatch/MultiDispatchStorage.h>
#include <Network/Packet/ManagePacketCmd.h>
#include <UserManage/ToolUserManageTable.h>
#include <ServerManage/ManageClientManager.h>
#include <Setup/SetupClient.h>
#include <Log/ServerLog.h>
#include <Network/Packet/WrapPacket.h>
#include <mmsystem.h>
enum ManageToolServerConst
{
MANAGE_TOOL_SERVER_DEFAULT_DISPATCH_NUM = 10
};
CManageToolServerDispatch::CManageToolServerDispatch(CSession& Session)
: CRylServerDispatch(Session, MANAGE_TOOL_SERVER_DEFAULT_DISPATCH_NUM),
m_bAuthorized(false), m_dwLastPingRecvTime(timeGetTime())
{
memset(&m_UserInfo, 0, sizeof(ServerManage::UserInfo));
DETLOG1(g_Log, "this:0x%p/CManageToolServerDispatch Created", this);
}
CManageToolServerDispatch::~CManageToolServerDispatch()
{
DETLOG1(g_Log, "this:0x%p/CManageToolServerDispatch Destroyed", this);
}
void CManageToolServerDispatch::Connected()
{
// 인증 성공시 LoginTable에 삽입된다.
DETLOG1(g_Log, "this:0x%p/CManageToolServerDispatch Connected", this);
}
void CManageToolServerDispatch::Disconnected()
{
if(0 != m_UserInfo.szID[0])
{
CToolUserManager::GetInstance().Logout(m_UserInfo.szID);
}
DETLOG1(g_Log, "this:0x%p/CManageToolServerDispatch Disconnected", this);
}
bool CManageToolServerDispatch::Dispatch()
{
unsigned long dwCurrentTime = timeGetTime();
// 2분 동안 핑을 못받으면 접속을 끊는다.
if (1000 * 60 * 2 < dwCurrentTime - m_dwLastPingRecvTime)
{
INFLOG4(g_Log, "Disconnect by ping %s:%d / %u / %u ",
GetRemoteAddr().get_addr_string(), GetRemoteAddr().get_port_in(),
dwCurrentTime, m_dwLastPingRecvTime);
return false;
}
return CRylServerDispatch::Dispatch();
}
bool CManageToolServerDispatch::DispatchPacket(PktBase* lpPktBase)
{
PktBase::LengthType nPacketLen = lpPktBase->GetLen();
bool bResult = true;
const TCHAR* szErrorString = 0;
bool bSendInvalidUserPacketAck = false;
bool bSendInvalidManagePacketAck = false;
if (ServerManage::CMD::Ping == lpPktBase->GetCmd())
{
m_dwLastPingRecvTime = timeGetTime();
PktBase pktBase;
memset(&pktBase, 0, sizeof(PktBase));
pktBase.SetServerInfo(m_dwLastPingRecvTime);
if (PacketWrap::WrapHeader(reinterpret_cast<char*>(&pktBase),
sizeof(PktBase), ServerManage::CMD::Ping, pktBase.GetState(), pktBase.GetError()))
{
GetSendStream().PutBuffer(reinterpret_cast<char*>(&pktBase),
sizeof(PktBase), ServerManage::CMD::Ping);
}
}
else if(ServerManage::CMD::AuthUser == lpPktBase->GetCmd())
{
if(!AuthUser(lpPktBase))
{
szErrorString = "Authorize failed.";
}
else
{
m_bAuthorized = true;
// 인증이 성공하면 RunInfo를 전송한다.
if(!CManageClientManager::SendRunInfo(GetSession(),
CManageClientManager::GetInstance().GetRunInfoTable()))
{
ERRLOG3(g_Log, "SS:0x%p/DP:0x%p/IP:%15s/Send runInfo failed",
&GetSession(), this, GetSession().GetRemoteAddr().get_addr_string());
}
}
}
else if(m_bAuthorized)
{
switch(lpPktBase->GetCmd())
{
// 다음 커맨드들은, RunID가 속한 서버로 메시지를 Relay한다.
// Relay하지 못한 경우는 실패를 돌려준다.
case ServerManage::CMD::RunProcess:
case ServerManage::CMD::QuitProcess:
case ServerManage::CMD::ForceTerminate:
case ServerManage::CMD::ProcessStatus:
case ServerManage::CMD::RelayCommand:
case ServerManage::CMD::AutoPatch:
case ServerManage::CMD::ChangeSetup:
case ServerManage::CMD::ReloadSetup:
case ServerManage::CMD::ExecuteCommand:
if(CToolUserManager::GetInstance().IsManageUser(m_UserInfo) &&
(m_UserInfo.usAdminLevel == CToolUserManager::MASTER
|| m_UserInfo.usAdminLevel == CToolUserManager::GENERAL))
{
bResult = RelayPacketToManageClient(lpPktBase);
}
else
{
bSendInvalidManagePacketAck = true;
}
break;
case ServerManage::CMD::AddUser:
if(CToolUserManager::GetInstance().IsManageUser(m_UserInfo) &&
m_UserInfo.usAdminLevel == CToolUserManager::MASTER)
{
bResult = AddUser(lpPktBase);
}
else
{
bSendInvalidUserPacketAck = true;
}
break;
case ServerManage::CMD::DelUser:
if(CToolUserManager::GetInstance().IsManageUser(m_UserInfo) &&
m_UserInfo.usAdminLevel == CToolUserManager::MASTER)
{
bResult = DelUser(lpPktBase);
}
else
{
bSendInvalidUserPacketAck = true;
}
break;
case ServerManage::CMD::ModUser:
if(CToolUserManager::GetInstance().IsManageUser(m_UserInfo) &&
m_UserInfo.usAdminLevel == CToolUserManager::MASTER)
{
bResult = ModUser(lpPktBase);
}
else
{
bSendInvalidUserPacketAck = true;
}
break;
case ServerManage::CMD::RequestPromote:
if(m_UserInfo.usAdminLevel == CToolUserManager::MASTER ||
m_UserInfo.usAdminLevel == CToolUserManager::GENERAL)
{
bResult = RequestPromote(lpPktBase);
}
else
{
bSendInvalidUserPacketAck = true;
}
break;
case ServerManage::CMD::RequestUserReaction:
if(m_UserInfo.usAdminLevel == CToolUserManager::MASTER ||
m_UserInfo.usAdminLevel == CToolUserManager::GENERAL)
{
bResult = ProcessUserReaction(lpPktBase);
}
else
{
bSendInvalidUserPacketAck = true;
}
break;
case ServerManage::CMD::UserList:
if(m_UserInfo.usAdminLevel == CToolUserManager::MASTER)
{
bResult = UserList(lpPktBase);
}
else
{
bSendInvalidUserPacketAck = true;
}
break;
default:
szErrorString = "Unknown packet. Cannot process.";
break;
}
}
else
{
szErrorString = "Unauthorized user send command. Cannot process.";
}
if(!bResult)
{
szErrorString = "Packet process failed.";
}
if(bSendInvalidManagePacketAck)
{
ServerManage::SendManagePacket(GetSession(), lpPktBase->GetCmd(),
0, 0, 0, 0, 0, 0, 0, ServerManage::INVALID_MANAGE_RIGHTS);
}
if(bSendInvalidUserPacketAck)
{
ServerManage::SendUserInfo(GetBufferFactory(), &GetSession(), 0, 0,
lpPktBase->GetCmd(), ServerManage::INVALID_USERMANAGE_RIGHTS);
}
if(0 != szErrorString)
{
in_addr addr;
addr.S_un.S_addr = m_UserInfo.dwIP;
ERRLOG5(g_Log, "ID:%s/Name:%s/IP:%s/Cmd:0x%02x/%s",
m_UserInfo.szID, m_UserInfo.szFullName, inet_ntoa(addr),
lpPktBase->GetCmd(), szErrorString);
}
return true;
}
bool CManageToolServerDispatch::RelayPacketToManageClient(PktBase* lpPktBase)
{
unsigned char cError = 0;
ServerManage::ManageCommand* lpManageCommand =
reinterpret_cast<ServerManage::ManageCommand*>(lpPktBase);
if(!ServerManage::CheckManagePacketLength(lpPktBase))
{
cError = ServerManage::INVALID_MANAGE_PACKET_ERROR;
}
if(CManageClientManager::MAX_RUNID == lpManageCommand->dwRunID)
{
CManageServerDispatch::GetDispatchTable().Process(
ServerManage::CSendManagePacketToClient(*lpManageCommand,
reinterpret_cast<char*>(lpManageCommand + 1)));
}
else
{
ServerManage::RunInfo runInfo;
if(CManageClientManager::GetInstance().GetRunInfo(
lpManageCommand->dwRunID, runInfo))
{
GET_MULTI_DISPATCH(lpManageServerDispatch,
runInfo.m_dwServerIP,
CManageServerDispatch,
CManageServerDispatch::GetDispatchTable());
if(0 != lpManageServerDispatch)
{
DETLOG4(g_Log, "ID:%s/FullName:%s/Send Relay Packet(Cmd:%d), RunID:%u",
m_UserInfo.szID, m_UserInfo.szFullName,
lpManageCommand->GetCmd(), lpManageCommand->dwRunID);
if(!ServerManage::SendManagePacket(lpManageServerDispatch->GetSession(),
lpManageCommand->GetCmd(), lpManageCommand->nMessage,
lpManageCommand->wParam, lpManageCommand->lParam,
lpManageCommand->dwRunID, lpManageCommand->usDataLen, lpManageCommand->usFlags,
reinterpret_cast<char*>(lpManageCommand + 1), 0))
{
cError = ServerManage::SEND_MANAGE_COMMAND_ERROR;
}
}
else
{
cError = ServerManage::CANNOT_FIND_CLIENT_DISPATCH;
}
}
else
{
cError = ServerManage::UNKNOWN_RUN_INFO;
}
}
return ServerManage::SendManagePacket(GetSession(),
lpPktBase->GetCmd(), 0, 0, 0, 0, 0, 0, 0, cError);
}

View File

@@ -0,0 +1,44 @@
#ifndef _GM_MANAGE_TOOL_SERVER_DISPATCH_H_
#define _GM_MANAGE_TOOL_SERVER_DISPATCH_H_
#include <Network/Packet/ManagePacketCmd.h>
#include <Network/Dispatch/RylServerDispatch.h>
// forward decl.
class CToolUserManager;
class CManageToolServerDispatch : public CRylServerDispatch
{
public:
CManageToolServerDispatch(CSession& Session);
virtual ~CManageToolServerDispatch();
const ServerManage::UserInfo& GetUserInfo() const { return m_UserInfo; }
private:
virtual void Connected();
virtual void Disconnected();
virtual bool Dispatch();
virtual bool DispatchPacket(PktBase* lpPktBase);
bool RelayPacketToManageClient(PktBase* lpPktBase);
bool AuthUser(PktBase* lpPktBase);
bool AddUser(PktBase* lpPktBase);
bool DelUser(PktBase* lpPktBase);
bool ModUser(PktBase* lpPktBase);
bool RequestPromote(PktBase* lpPktBase);
bool ProcessUserReaction(PktBase* lpPktBase);
bool UserList(PktBase* lpPktBase);
ServerManage::UserInfo m_UserInfo;
unsigned long m_dwLastPingRecvTime;
bool m_bAuthorized;
};
#endif

View File

@@ -0,0 +1,308 @@
#include "stdafx.h"
#include "ManageToolServerDispatch.h"
#include <tchar.h>
#include <Log/ServerLog.h>
#include <UserManage/ToolUserManageTable.h>
#include <Network/Session/Session.h>
#include <Network/Dispatch/SendManagePacket.h>
bool CManageToolServerDispatch::AuthUser(PktBase* lpPktBase)
{
unsigned char cError = 0;
ServerManage::UserCommand* lpUserCommand =
reinterpret_cast<ServerManage::UserCommand*>(lpPktBase);
ServerManage::UserInfo* lpUserInfo =
reinterpret_cast<ServerManage::UserInfo*>(lpUserCommand + 1);
if(!ServerManage::CheckUserPacketLength(lpPktBase, 1))
{
cError = ServerManage::INVALID_USER_PACKET_ERROR;
}
if(0 == cError)
{
m_UserInfo = *lpUserInfo;
m_UserInfo.dwIP = GetSession().GetRemoteAddr().get_addr_in().sin_addr.S_un.S_addr;
// 인증 성공시 LoginTable에 삽입된다.
cError = CToolUserManager::GetInstance().Authorize(*this, m_UserInfo);
if (cError != ServerManage::NO_USER_COMMAND_ERROR)
{
ERRLOG2(g_Log, "ID:%s/IP:%s/Authorize failed",
m_UserInfo.szID, GetSession().GetRemoteAddr().get_addr_string());
}
}
if(0 == cError)
{
DETLOG2(g_Log, "ID:%s/IP:%s/Authorize success",
m_UserInfo.szID, GetSession().GetRemoteAddr().get_addr_string());
// 다른 유저들에게 로그인 정보를 보낸다.
ServerManage::SendUserInfo(GetBufferFactory(), 0, &m_UserInfo, 1,
ServerManage::CMD::UserLogin, 0);
// 현재 관리자 정보를 준다.
ServerManage::SendUserInfo(GetBufferFactory(), 0,
&CToolUserManager::GetInstance().GetManageUser(), 1,
ServerManage::CMD::ManagerInfo, 0);
// 다른 유저들의 로그인 정보를 받는다.
CToolUserManager::GetInstance().SendAllLoginUserInfo(GetSession());
#pragma todo("서버 Setup을 준다")
}
ServerManage::SendUserInfo(GetBufferFactory(), &GetSession(), &m_UserInfo, 1,
ServerManage::CMD::AuthUser, cError);
return (0 == cError);
}
bool CManageToolServerDispatch::AddUser(PktBase* lpPktBase)
{
unsigned char cError = 0;
ServerManage::UserCommand* lpUserCommand =
reinterpret_cast<ServerManage::UserCommand*>(lpPktBase);
ServerManage::UserInfo* lpUserInfo =
reinterpret_cast<ServerManage::UserInfo*>(lpUserCommand + 1);
if(!ServerManage::CheckUserPacketLength(lpPktBase, 1))
{
cError = ServerManage::INVALID_USER_PACKET_ERROR;
}
if(0 == cError && !CToolUserManager::GetInstance().AddUser(*lpUserInfo))
{
ERRLOG3(g_Log, "ID:%s/IP:%s/Adduser failed (ID:%s)",
m_UserInfo.szID, GetSession().GetRemoteAddr().get_addr_string(), lpUserInfo->szID);
cError = ServerManage::ADD_USER_FAILED;
}
DETLOG3(g_Log, "ID:%s/IP:%s/Adduser success",
m_UserInfo.szID, GetSession().GetRemoteAddr().get_addr_string(), lpUserInfo->szID);
memset(lpUserInfo->szPassword, 0, ServerManage::UserInfo::PASS_LEN);
return ServerManage::SendUserInfo(GetBufferFactory(), &GetSession(), lpUserInfo, 1,
ServerManage::CMD::AddUser, cError);
}
bool CManageToolServerDispatch::DelUser(PktBase* lpPktBase)
{
unsigned char cError = 0;
ServerManage::UserCommand* lpUserCommand =
reinterpret_cast<ServerManage::UserCommand*>(lpPktBase);
ServerManage::UserInfo* lpUserInfo =
reinterpret_cast<ServerManage::UserInfo*>(lpUserCommand + 1);
if(!ServerManage::CheckUserPacketLength(lpPktBase, 1))
{
cError = ServerManage::INVALID_USER_PACKET_ERROR;
}
if(0 == cError && !CToolUserManager::GetInstance().DelUser(lpUserInfo->szID))
{
ERRLOG3(g_Log, "ID:%s/IP:%s/Delete user failed (ID:%s)",
m_UserInfo.szID, GetSession().GetRemoteAddr().get_addr_string(), lpUserInfo->szID);
cError = ServerManage::DELETE_USER_FAILED;
}
DETLOG3(g_Log, "ID:%s/IP:%s/Delete user success",
m_UserInfo.szID, GetSession().GetRemoteAddr().get_addr_string(), lpUserInfo->szID);
return ServerManage::SendUserInfo(GetBufferFactory(), &GetSession(), lpUserInfo, 1,
ServerManage::CMD::DelUser, cError);
}
bool CManageToolServerDispatch::ModUser(PktBase* lpPktBase)
{
unsigned char cError = 0;
ServerManage::UserCommand* lpUserCommand =
reinterpret_cast<ServerManage::UserCommand*>(lpPktBase);
ServerManage::UserInfo* lpUserInfo =
reinterpret_cast<ServerManage::UserInfo*>(lpUserCommand + 1);
if(!ServerManage::CheckUserPacketLength(lpPktBase, 1))
{
cError = ServerManage::INVALID_USER_PACKET_ERROR;
}
if(0 == cError && !CToolUserManager::GetInstance().ModifyUser(*lpUserInfo))
{
ERRLOG3(g_Log, "ID:%s/IP:%s/Modify user failed (ID:%s)",
m_UserInfo.szID, GetSession().GetRemoteAddr().get_addr_string(), lpUserInfo->szID);
cError = ServerManage::MODIFY_USER_FAILED;
}
DETLOG3(g_Log, "ID:%s/IP:%s/Modify user success",
m_UserInfo.szID, GetSession().GetRemoteAddr().get_addr_string(), lpUserInfo->szID);
memset(lpUserInfo->szPassword, 0, ServerManage::UserInfo::PASS_LEN);
return ServerManage::SendUserInfo(GetBufferFactory(), &GetSession(), lpUserInfo, 1,
ServerManage::CMD::ModUser, cError);
}
bool CManageToolServerDispatch::UserList(PktBase* lpPktBase)
{
unsigned char cError = 0;
ServerManage::UserCommand* lpUserCommand =
reinterpret_cast<ServerManage::UserCommand*>(lpPktBase);
if(!ServerManage::CheckUserPacketLength(lpPktBase, 0))
{
cError = ServerManage::INVALID_USER_PACKET_ERROR;
}
if(0 == cError && !CToolUserManager::GetInstance().SendAllUserInfo(GetSession()))
{
ERRLOG2(g_Log, "ID:%s/IP:%s/Send userlist failed",
m_UserInfo.szID, GetSession().GetRemoteAddr().get_addr_string());
cError = ServerManage::SEND_USER_LIST_FAILED;
}
DETLOG2(g_Log, "ID:%s/IP:%s/Send userlist success",
m_UserInfo.szID, GetSession().GetRemoteAddr().get_addr_string());
return ServerManage::SendUserInfo(GetBufferFactory(), &GetSession(), 0, 0,
ServerManage::CMD::UserList, cError);
}
bool CManageToolServerDispatch::RequestPromote(PktBase* lpPktBase)
{
unsigned char cError = 0;
ServerManage::UserCommand* lpUserCommand =
reinterpret_cast<ServerManage::UserCommand*>(lpPktBase);
ServerManage::UserInfo* lpUserInfo =
reinterpret_cast<ServerManage::UserInfo*>(lpUserCommand + 1);
if(!ServerManage::CheckUserPacketLength(lpPktBase, 1))
{
cError = ServerManage::INVALID_USER_PACKET_ERROR;
}
if(0 == cError)
{
const ServerManage::UserInfo& masterUser = CToolUserManager::GetInstance().GetManageUser();
if(0 == masterUser.szID[0] || m_UserInfo.usAdminLevel == CToolUserManager::MASTER)
{
// 현재 Promote유저가 있는지 살핀다. 없거나, Master면 바로 Promote를 하고 Broadcast를 한다.
CToolUserManager::GetInstance().Promote(m_UserInfo);
ServerManage::SendUserInfo(GetBufferFactory(), 0,
&m_UserInfo, 1, ServerManage::CMD::ManagerInfo, 0);
}
else if(m_UserInfo.usAdminLevel == CToolUserManager::GENERAL)
{
// 현재 Promote유저가 있고, 내가 General레벨이면, 정중히 요청을 한다.
CManageToolServerDispatch* lpToolUserDispatch =
CToolUserManager::GetInstance().GetManageUserDispatch();
ServerManage::UserInfo userInfo = m_UserInfo;
userInfo.usSubCommand = ServerManage::CMD::REQUEST_TAKEBACK_PROMOTE;
// 아직 연결되어 있으면 요청 패킷을 보냄.
if(0 == lpToolUserDispatch
|| !ServerManage::SendUserInfo(GetBufferFactory(),
&lpToolUserDispatch->GetSession(), &userInfo, 1,
ServerManage::CMD::RequestUserReaction, 0))
{
cError = ServerManage::PROMOTE_TAKEBACK_FAILED;
}
}
else
{
cError = ServerManage::PROMOTE_USER_FAILED;
}
}
if(0 != cError)
{
ERRLOG3(g_Log, "ID:%s/IP:%s/Promote user failed (ID:%s)",
m_UserInfo.szID, GetSession().GetRemoteAddr().get_addr_string(), lpUserInfo->szID);
ServerManage::SendUserInfo(GetBufferFactory(), &GetSession(), 0, 0,
ServerManage::CMD::RequestPromote, cError);
}
return true;
}
bool CManageToolServerDispatch::ProcessUserReaction(PktBase* lpPktBase)
{
unsigned char cError = 0;
ServerManage::UserCommand* lpUserCommand =
reinterpret_cast<ServerManage::UserCommand*>(lpPktBase);
ServerManage::UserInfo* lpUserInfo =
reinterpret_cast<ServerManage::UserInfo*>(lpUserCommand + 1);
if(!ServerManage::CheckUserPacketLength(lpPktBase, 1))
{
cError = ServerManage::INVALID_USER_PACKET_ERROR;
}
CManageToolServerDispatch* lpRequestDispatch = 0;
if(0 == cError)
{
switch(lpUserInfo->usSubCommand)
{
case ServerManage::CMD::ACK_TAKEBACK_PROMOTE:
// 처음 요청자를 찾아서 Promote 성공 패킷을 보낸다.
lpRequestDispatch = CToolUserManager::GetInstance().GetUserDispatch(lpUserInfo->szID);
if(0 != lpRequestDispatch)
{
ServerManage::UserInfo manager = lpRequestDispatch->GetUserInfo();
// Promote 처리.
CToolUserManager::GetInstance().Promote(manager);
// 누가 Manager인지 만천하에 알린다.
ServerManage::SendUserInfo(GetBufferFactory(), 0,
&manager, 1, ServerManage::CMD::ManagerInfo, 0);
// 본인에게 Ack.
ServerManage::SendUserInfo(GetBufferFactory(), &lpRequestDispatch->GetSession(),
&manager, 1, ServerManage::CMD::RequestPromote, 0);
}
break;
case ServerManage::CMD::NAK_TAKEBACK_PROMOTE:
// 처음 요청자를 찾아서 Promote 실패 패킷을 보낸다.
lpRequestDispatch = CToolUserManager::GetInstance().GetUserDispatch(lpUserInfo->szID);
if(0 != lpRequestDispatch)
{
ServerManage::SendUserInfo(GetBufferFactory(), &lpRequestDispatch->GetSession(),
&m_UserInfo, 1, ServerManage::CMD::RequestPromote, ServerManage::REJECTED_PROMOTE_USER);
}
break;
}
}
return true;
}

View File

@@ -0,0 +1,47 @@
#include "stdafx.h"
#include "StatServerDispatch.h"
#include <Network/Session/Session.h>
#include <Network/Packet/ManagePacketCmd.h>
#include <Log/ServerLog.h>
enum StatServerConst
{
STAT_SERVER_DEFAULT_DISPATCH_NUM = 10
};
CStatServerDispatch::CStatServerDispatch(CSession& Session)
: CRylServerDispatch(Session, STAT_SERVER_DEFAULT_DISPATCH_NUM)
{
DETLOG1(g_Log, "this:0x%p/CStatServerDispatch Created", this);
}
CStatServerDispatch::~CStatServerDispatch()
{
DETLOG1(g_Log, "this:0x%p/CStatServerDispatch Destroyed", this);
}
CSingleDispatch& CStatServerDispatch::GetDispatch()
{
static CSingleDispatch statServerDispatch;
return statServerDispatch;
}
void CStatServerDispatch::Connected()
{
GetDispatch().SetDispatch(this);
}
void CStatServerDispatch::Disconnected()
{
GetDispatch().RemoveDispatch(this);
}
bool CStatServerDispatch::DispatchPacket(PktBase* lpPktBase)
{
return true;
}

View File

@@ -0,0 +1,26 @@
#ifndef _STAT_SERVER_DISPATCH_H_
#define _STAT_SERVER_DISPATCH_H_
#include <Network/Packet/ManagePacketCmd.h>
#include <Network/Dispatch/RylServerDispatch.h>
#include <Network/Dispatch/SingleDispatchStorage.h>
class CStatServerDispatch : public CRylServerDispatch
{
public:
CStatServerDispatch(CSession& Session);
virtual ~CStatServerDispatch();
static CSingleDispatch& GetDispatch();
private:
virtual void Connected();
virtual void Disconnected();
virtual bool DispatchPacket(PktBase* lpPktBase);
};
#endif

View File

@@ -0,0 +1,58 @@
#include "stdafx.h"
#include "StatServerMultiDispatch.h"
#include <Network/Session/Session.h>
#include <Network/Dispatch/MultiDispatchStorage.h>
#include <Log/ServerLog.h>
#include <Setup/SetupClient.h>
enum StatServerConst
{
STAT_SERVER_DEFAULT_DISPATCH_NUM = 10
};
CMultiDispatch& CStatServerMultiDispatch::GetDispatchTable()
{
static CMultiDispatch multiDispatch;
return multiDispatch;
}
CStatServerMultiDispatch::CStatServerMultiDispatch(CSession& Session)
: CRylServerDispatch(Session, STAT_SERVER_DEFAULT_DISPATCH_NUM)
{
DETLOG1(g_Log, "this:0x%p/CStatServerMultiDispatch Created", this);
}
CStatServerMultiDispatch::~CStatServerMultiDispatch()
{
DETLOG1(g_Log, "this:0x%p/CStatServerMultiDispatch Destroyed", this);
}
void CStatServerMultiDispatch::Connected()
{
// 접속 IP를 key로 잡아서 세팅한다.
INET_Addr& remoteAddr = GetSession().GetRemoteAddr();
unsigned long dwDispatchID = remoteAddr.get_addr_in().sin_addr.S_un.S_addr;
GetDispatchTable().SetDispatch(dwDispatchID, this);
DETLOG2(g_Log, "this:0x%p/Key:%u/CStatServerMultiDispatch Connected", this, dwDispatchID);
}
void CStatServerMultiDispatch::Disconnected()
{
// 접속 IP를 key로 잡아서 삭제한다.
INET_Addr& remoteAddr = GetSession().GetRemoteAddr();
unsigned long dwDispatchID = remoteAddr.get_addr_in().sin_addr.S_un.S_addr;
GetDispatchTable().RemoveDispatch(dwDispatchID);
DETLOG2(g_Log, "this:0x%p/Key:%u/CStatServerMultiDispatch Disconnected", this, dwDispatchID);
}
bool CStatServerMultiDispatch::DispatchPacket(PktBase* lpPktBase)
{
return true;
}

View File

@@ -0,0 +1,25 @@
#ifndef _STAT_SERVER_MULTI_DISPATCH_H_
#define _STAT_SERVER_MULTI_DISPATCH_H_
#include <Network/Packet/ManagePacketCmd.h>
#include <Network/Dispatch/RylServerDispatch.h>
#include <Network/Dispatch/MultiDispatchStorage.h>
class CStatServerMultiDispatch : public CRylServerDispatch
{
public:
static CMultiDispatch& GetDispatchTable();
CStatServerMultiDispatch(CSession& Session);
virtual ~CStatServerMultiDispatch();
private:
virtual void Connected();
virtual void Disconnected();
virtual bool DispatchPacket(PktBase* lpPktBase);
};
#endif

View File

@@ -0,0 +1,208 @@
#include "stdafx.h"
#include "SendManagePacket.h"
#include <tchar.h>
#include <Network/Session/Session.h>
#include <Network/Dispatch/Dispatch.h>
#include <Network/Packet/WrapPacket.h>
#include <Network/Packet/ManagePacketCmd.h>
#include <Stream/Buffer/Buffer.h>
#include <Stream/Buffer/BufferFactory.h>
#include <Utility/Compress/MiniLZO/MiniLZOWrapper.h>
#include <UserManage/ToolUserManageTable.h>
#include <Log/ServerLog.h>
/*!
\brief 관리 패킷 전송
\param Session 세션
\param cCmd 커맨드
\param nMessage 윈도우 메시지 번호
\param wParam WPARAM
\param lParam LPARAM
\param dwRunID RunID
\param usDataLen 데이터 길이
\param usFlags 추가 데이터 플래그
\param lpData 보낼 데이터
\param cError 에러 커맨드
\return 패킷 전송 성공 여부
*/
bool ServerManage::SendManagePacket(CSession& Session,
unsigned char cCmd,
unsigned int nMessage,
WPARAM wParam,
LPARAM lParam,
unsigned long dwRunID,
unsigned short usDataLen,
unsigned short usFlags,
const void* lpData,
unsigned char cError)
{
CBuffer* lpBuffer = CREATE_BUFFER(Session.GetPolicy().GetBufferFactory(),
(sizeof(ManageCommand) + usDataLen));
if(0 != lpBuffer)
{
ManageCommand* lpManageCommand = reinterpret_cast<ManageCommand*>(lpBuffer->wr_ptr());
lpManageCommand->nMessage = nMessage; // 메시지 번호
lpManageCommand->wParam = wParam; // 파라미터1
lpManageCommand->lParam = lParam; // 파라미터2
lpManageCommand->dwRunID = dwRunID; // 메세지 받을 곳의 IP
lpManageCommand->usDataLen = (0 != lpData) ? usDataLen : 0; // 추가 데이터 길이
lpManageCommand->usFlags = usFlags; // 기타 커맨드 (내용에 따라서 다름)
if(0 != lpData)
{
memcpy(reinterpret_cast<char*>(lpManageCommand + 1), lpData, usDataLen);
}
if(PacketWrap::WrapCrypt(lpBuffer, sizeof(ManageCommand) + usDataLen, cCmd, 0, cError)
&& Session.SendPending(lpBuffer))
{
return true;
}
SAFE_RELEASE_BUFFER(lpBuffer);
}
return false;
}
/*!
\brief 관리 패킷 전송
\param bufferFactory BufferFactory
\param lpTarget 세션. 0이면 Broadcast
\param lpUserInfo 유저 정보 (내부적으로 패스워드만 제거하고 보낸다)
\param cUserInfoNum 유저 정보 개수
\param cCommand 커맨드.
\param cError 에러.
\return 패킷 전송 성공 여부
*/
bool ServerManage::SendUserInfo(CBufferFactory& bufferFactory,
CSession* lpTarget,
const ServerManage::UserInfo* lpUserInfo,
unsigned char cUserInfoNum,
unsigned char cCommand,
unsigned char cError)
{
// 다른 유저들에게 자신이 추가되었다는 메시지를 던진다.
CBuffer* lpBuffer = CREATE_BUFFER(bufferFactory,
sizeof(ServerManage::UserCommand) + sizeof(ServerManage::UserInfo) * cUserInfoNum);
CBuffer* lpCompressedBuffer = CREATE_BUFFER(bufferFactory,
CMiniLZO::GetLeastCompressBuffer(sizeof(ServerManage::UserCommand) + sizeof(ServerManage::UserInfo) * cUserInfoNum));
if(0 != lpBuffer && 0 != lpCompressedBuffer)
{
ServerManage::UserCommand* lpUserCommand = reinterpret_cast<ServerManage::UserCommand*>(lpBuffer->wr_ptr());
ServerManage::UserInfo* lpFirstUserInfo = reinterpret_cast<ServerManage::UserInfo*>(lpUserCommand + 1);
ServerManage::UserInfo* lpLastUserInfo = lpFirstUserInfo + cUserInfoNum;
lpUserCommand->cUserInfoNum = cUserInfoNum;
std::copy(lpUserInfo, lpUserInfo + cUserInfoNum, lpFirstUserInfo);
for(ServerManage::UserInfo* lpTempUserInfo = lpFirstUserInfo;
lpTempUserInfo != lpLastUserInfo; ++lpTempUserInfo)
{
memset(lpTempUserInfo->szPassword, 0, sizeof(ServerManage::UserInfo::PASS_LEN) * sizeof(TCHAR));
}
if(PacketWrap::WrapCompress(lpCompressedBuffer, lpBuffer->rd_ptr(),
sizeof(ServerManage::UserCommand) + sizeof(ServerManage::UserInfo) * cUserInfoNum,
cCommand, 0, cError))
{
if(lpTarget)
{
if(lpTarget->SendPending(lpCompressedBuffer))
{
SAFE_RELEASE_BUFFER(lpBuffer);
return true;
}
}
else
{
CToolUserManager::GetInstance().SendToAllLoginUser(
lpCompressedBuffer->rd_ptr(), lpCompressedBuffer->length(), lpUserCommand->GetCmd());
SAFE_RELEASE_BUFFER(lpCompressedBuffer);
SAFE_RELEASE_BUFFER(lpBuffer);
return true;
}
}
}
SAFE_RELEASE_BUFFER(lpCompressedBuffer);
SAFE_RELEASE_BUFFER(lpBuffer);
return false;
}
bool ServerManage::CheckUserPacketLength(PktBase* lpPktBase, int nExpectUserInfoNum)
{
PktBase::LengthType nLength = lpPktBase->GetLen();
if(nLength < sizeof(ServerManage::UserCommand))
{
return false;
}
ServerManage::UserCommand* lpUserCommand = reinterpret_cast<ServerManage::UserCommand*>(lpPktBase);
ServerManage::UserInfo* lpUserInfo = reinterpret_cast<ServerManage::UserInfo*>(lpUserCommand + 1);
if(0 < nExpectUserInfoNum)
{
if(nExpectUserInfoNum != lpUserCommand->cUserInfoNum ||
nLength != sizeof(ServerManage::UserCommand) + sizeof(ServerManage::UserInfo) * nExpectUserInfoNum)
{
ERRLOG2(g_Log, "Invalid packet size : userinfo num : %d, packet size : %d",
lpUserCommand->cUserInfoNum, nLength);
return false;
}
}
else if(nLength != sizeof(ServerManage::UserCommand))
{
return false;
}
return true;
}
bool ServerManage::CheckManagePacketLength(PktBase* lpPktBase)
{
unsigned short usPacketLength = lpPktBase->GetLen();
ServerManage::ManageCommand* lpManageCommand =
reinterpret_cast<ServerManage::ManageCommand*>(lpPktBase);
if(usPacketLength < sizeof(ServerManage::ManageCommand) ||
(usPacketLength != lpManageCommand->usDataLen + sizeof(ServerManage::ManageCommand)))
{
ERRLOG2(g_Log, "Invalid packet size : DataLen : %d, Packet size : %d",
lpManageCommand->usDataLen, lpPktBase->GetLen());
return false;
}
return true;
}
ServerManage::CSendManagePacketToClient::CSendManagePacketToClient(ManageCommand& manageCommand,
const char* lpData)
: m_ManageCommand(manageCommand),
m_lpData(lpData)
{
}
bool ServerManage::CSendManagePacketToClient::operator() (CPacketDispatch& dispatch)
{
return SendManagePacket(dispatch.GetSession(),
m_ManageCommand.GetCmd(), m_ManageCommand.nMessage,
m_ManageCommand.wParam, m_ManageCommand.lParam,
m_ManageCommand.dwRunID, m_ManageCommand.usDataLen, m_ManageCommand.usFlags,
m_lpData, static_cast<unsigned char>(m_ManageCommand.GetError()));
}

View File

@@ -0,0 +1,67 @@
#ifndef _SEND_MANAGE_PACKET_H_
#define _SEND_MANAGE_PACKET_H_
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <winsock2.h>
#include <windows.h>
// forward decl.
struct PktBase;
class CSession;
class CBufferFactory;
class CPacketDispatch;
namespace ServerManage
{
// forward decl.
struct ManageCommand;
struct UserInfo;
bool CheckManagePacketLength(PktBase* lpPktBase);
bool CheckUserPacketLength(PktBase* lpPktBase, int nExpectUserInfoNum = -1);
// 서버 관리 패킷을 보낸다.
bool SendManagePacket(
CSession& Session, // 세션
unsigned char cCmd, // 커맨드
unsigned int nMessage, // 윈도우 메시지 번호
WPARAM wParam, // WPARAM
LPARAM lParam, // LPARAM
unsigned long dwRunID, // RunID
unsigned short usDataLen, // 데이터 길이
unsigned short usFlags, // 추가 데이터 플래그
const void* lpData, // 보낼 데이터
unsigned char cError); // 에러 커맨드
// 유저 정보 패킷을 보낸다.
bool SendUserInfo(
CBufferFactory& bufferFactory, // BufferFactory
CSession* lpTarget, // 세션. 0이면 Broadcast
const ServerManage::UserInfo* lpUserInfo, // ( )
unsigned char cUserInfoNum, // 유저 정보 개수
unsigned char cCommand, // 커맨드.
unsigned char cError); // 에러.
class CSendManagePacketToClient
{
public:
CSendManagePacketToClient(ManageCommand& manageCommand, const char* lpData);
bool operator() (CPacketDispatch& dispatch);
bool operator() (unsigned long dwKeyType, CPacketDispatch& dispatch)
{ return operator() (dispatch); }
private:
ManageCommand& m_ManageCommand;
const char* m_lpData;
};
};
#endif

View File

@@ -0,0 +1,29 @@
========================================================================
정적 라이브러리 : ServerManagerary 프로젝트 개요
========================================================================
응용 프로그램 마법사에서 이 ServerManagerary 라이브러리 프로젝트를 만들었습니다.
이 파일에는 ServerManagerary 응용 프로그램을 구성하는 각각의 파일에
들어 있는 요약 설명이 포함되어 있습니다.
ServerManagerary.vcproj
응용 프로그램 마법사를 사용하여 생성한 VC++ 프로젝트의 기본 프로젝트 파일입니다.
해당 파일을 생성한 Visual C++의 버전 정보를 비롯하여
응용 프로그램 마법사에서 선택한 플랫폼, 구성 및
프로젝트 기능에 대한 정보가 들어 있습니다.
/////////////////////////////////////////////////////////////////////////////
StdAfx.h 및 StdAfx.cpp는
ServerManagerary.pch라는 이름의 PCH(미리 컴파일된 헤더) 파일과
StdAfx.obj라는 이름의 미리 컴파일된 형식 파일을 빌드하는 데 사용됩니다.
/////////////////////////////////////////////////////////////////////////////
기타 참고:
응용 프로그램 마법사에서 사용하는 "TODO:" 주석은 사용자가 추가하거나 사용자 지정해야 하는
소스 코드 부분을 나타냅니다.
/////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,537 @@
#include "stdafx.h"
#include "ManageClientManager.h"
#include <DB/SQLite.h>
#include <DB/ManageServerDB.h>
#include <Log/ServerLog.h>
CManageClientManager& CManageClientManager::GetInstance()
{
static CManageClientManager manageClientManager(CManageServerDB::GetInstance());
return manageClientManager;
}
CManageClientManager::CManageClientManager(CManageServerDB& manageServerDB)
: m_ManageServerDB(manageServerDB)
{
ReloadRunInfo();
}
CManageClientManager::~CManageClientManager()
{
}
// ----------------------------------------------------------------------------------------------
// 서버 정보 관련
bool CManageClientManager::Add(InfoType eInfoType,
const ServerManage::RunInfo& runInfo,
unsigned long& dwID_Out)
{
const int MAX_QUERY_LEN = 512;
char szQuery[MAX_QUERY_LEN];
int nQueryLen = -1;
switch(eInfoType)
{
case SERVER_INFO:
nQueryLen = _snprintf(szQuery, MAX_QUERY_LEN - 1,
"INSERT INTO TblServerInfo values(%d, '%s')",
runInfo.m_dwServerIP, runInfo.m_szServerName);
break;
case RUN_PATH_INFO:
nQueryLen = _snprintf(szQuery, MAX_QUERY_LEN - 1,
"INSERT INTO TblRunPath values(NULL, '%s')", runInfo.m_szPath);
break;
case OPTION_INFO:
nQueryLen = _snprintf(szQuery, MAX_QUERY_LEN - 1,
"INSERT INTO TblRunOptions values(NULL, '%s')", runInfo.m_szOption);
break;
case RUN_INFO:
nQueryLen = _snprintf(szQuery, MAX_QUERY_LEN - 1,
"INSERT INTO TblRunInfo values(NULL, %d, %d, %d)",
runInfo.m_dwPathID, runInfo.m_dwOptionID, runInfo.m_dwServerIP);
break;
default:
ERRLOG1(g_Log, "Unknown InfoType : %d", eInfoType);
return false;
};
szQuery[MAX_QUERY_LEN - 1] = 0;
if(nQueryLen <= 0)
{
ERRLOG1(g_Log, "Make query failed : %s", szQuery);
return false;
}
CSQLite::Dataset executeQuery(m_ManageServerDB.GetSQLite(), szQuery);
if(!executeQuery.Compile() || !executeQuery.Execute())
{
if(0 != executeQuery.GetLastError())
{
ERRLOG2(g_Log, "Add failed : error : %s(Query:%s)",
executeQuery.GetLastError(), szQuery);
}
return false;
}
dwID_Out = m_ManageServerDB.GetSQLite().GetLastInsertRowID();
return ReloadRunInfo();
}
bool CManageClientManager::Modify(InfoType eInfoType, const ServerManage::RunInfo& runInfo)
{
const int MAX_QUERY_LEN = 512;
char szQuery[MAX_QUERY_LEN];
int nQueryLen = -1;
switch(eInfoType)
{
case SERVER_INFO:
nQueryLen = _snprintf(szQuery, MAX_QUERY_LEN - 1,
"UPDATE TblServerInfo SET ServerName = '%s' WHERE IP = %d",
runInfo.m_szServerName, runInfo.m_dwServerIP);
break;
case RUN_PATH_INFO:
nQueryLen = _snprintf(szQuery, MAX_QUERY_LEN - 1,
"UPDATE TblRunPath SET RunPath = '%s' WHERE PathID = %d",
runInfo.m_szPath, runInfo.m_dwPathID);
break;
case OPTION_INFO:
nQueryLen = _snprintf(szQuery, MAX_QUERY_LEN - 1,
"UPDATE TblRunOptions SET RunOption = '%s' WHERE OptionID = %d",
runInfo.m_szOption, runInfo.m_dwOptionID);
break;
case RUN_INFO:
nQueryLen = _snprintf(szQuery, MAX_QUERY_LEN - 1,
"UPDATE TblRunInfo SET PathID = %d, OptionID = %d, ServerIP = %d WHERE RunID = %d",
runInfo.m_dwPathID, runInfo.m_dwOptionID, runInfo.m_dwServerIP, runInfo.m_dwRunID);
break;
default:
ERRLOG1(g_Log, "Unknown InfoType : %d", eInfoType);
return false;
};
szQuery[MAX_QUERY_LEN - 1] = 0;
if(nQueryLen <= 0)
{
ERRLOG1(g_Log, "Make query failed : %s", szQuery);
return false;
}
CSQLite::Dataset executeQuery(m_ManageServerDB.GetSQLite(), szQuery);
if(!executeQuery.Compile() || !executeQuery.Execute())
{
if(0 != executeQuery.GetLastError())
{
ERRLOG2(g_Log, "Modify failed : error : %s(Query:%s)",
executeQuery.GetLastError(), szQuery);
}
return false;
}
return ReloadRunInfo();
}
bool CManageClientManager::Remove(InfoType eInfoType, unsigned long dwID, bool bDeleteRelated)
{
const int MAX_QUERY_LEN = 512;
char szQuery[MAX_QUERY_LEN];
char szDeleteRelated[MAX_QUERY_LEN];
const char* szRelatedKey = 0;
int nQueryLen = -1;
switch(eInfoType)
{
case SERVER_INFO:
nQueryLen = _snprintf(szQuery, MAX_QUERY_LEN - 1,
"DELETE FROM TblServerInfo WHERE IP = %d", dwID);
szRelatedKey = "ServerIP";
break;
case RUN_PATH_INFO:
nQueryLen = _snprintf(szQuery, MAX_QUERY_LEN - 1,
"DELETE FROM TblRunPath WHERE PathID = %d;", dwID);
szRelatedKey = "PathID";
break;
case OPTION_INFO:
nQueryLen = _snprintf(szQuery, MAX_QUERY_LEN - 1,
"DELETE FROM TblRunOptions WHERE OptionID = %d;", dwID);
szRelatedKey = "OptionID";
break;
case RUN_INFO:
nQueryLen = _snprintf(szQuery, MAX_QUERY_LEN - 1,
"DELETE FROM TblRunInfo WHERE RunID = %d", dwID);
break;
default:
ERRLOG1(g_Log, "Unknown InfoType : %d", eInfoType);
return false;
};
szQuery[MAX_QUERY_LEN - 1] = 0;
if(nQueryLen <= 0)
{
ERRLOG1(g_Log, "Make query failed : %s", szQuery);
return false;
}
else
{
CSQLite::Dataset executeQuery(m_ManageServerDB.GetSQLite(), szQuery);
if(!executeQuery.Compile() || !executeQuery.Execute())
{
if(0 != executeQuery.GetLastError())
{
ERRLOG2(g_Log, "Delete failed : error : %s(Query:%s)",
executeQuery.GetLastError(), szQuery);
}
return false;
}
if(bDeleteRelated && 0 != szRelatedKey)
{
nQueryLen = _snprintf(szDeleteRelated, MAX_QUERY_LEN - 1,
"DELETE FROM TblRunInfo WHERE %s = %d;", szRelatedKey, dwID);
if(nQueryLen <= 0)
{
ERRLOG1(g_Log, "Make query failed : %s", szDeleteRelated);
return false;
}
CSQLite::Dataset deleteRelatedQuery(m_ManageServerDB.GetSQLite(), szDeleteRelated);
if(!deleteRelatedQuery.Compile() || !deleteRelatedQuery.Execute())
{
if(0 != deleteRelatedQuery.GetLastError())
{
ERRLOG2(g_Log, "Delete related failed : error : %s(Query:%s)",
deleteRelatedQuery.GetLastError(), szDeleteRelated);
}
return false;
}
}
}
return ReloadRunInfo();
}
int GetServerInfoCallback(void *callBackArg, int nColumnNum,
char **szColumnValues, char **szColumnNames)
{
if(2 == nColumnNum)
{
CManageClientManager::RunTable& runTable =
*reinterpret_cast<CManageClientManager::RunTable*>(callBackArg);
ServerManage::RunInfo runInfo;
memset(&runInfo, 0, sizeof(ServerManage::RunInfo));
runInfo.m_dwServerIP = atol(szColumnValues[0]);
_snprintf(runInfo.m_szServerName, ServerManage::RunInfo::MAX_SERVER_NAME - 1,
"%s", szColumnValues[1]);
runInfo.m_szServerName[ServerManage::RunInfo::MAX_SERVER_NAME - 1] = 0;
if(!runTable.insert(CManageClientManager::RunTable::value_type(
runInfo.m_dwServerIP, runInfo)).second)
{
ERRLOG1(g_Log, "Insert failed. Key : %d", runInfo.m_dwServerIP);
}
}
return 0;
}
int GetPathInfoCallback(void *callBackArg, int nColumnNum,
char **szColumnValues, char **szColumnNames)
{
if(2 == nColumnNum)
{
CManageClientManager::RunTable& runTable =
*reinterpret_cast<CManageClientManager::RunTable*>(callBackArg);
ServerManage::RunInfo runInfo;
memset(&runInfo, 0, sizeof(ServerManage::RunInfo));
runInfo.m_dwPathID = atol(szColumnValues[0]);
_snprintf(runInfo.m_szPath, ServerManage::RunInfo::MAX_PATH_LEN - 1,
"%s", szColumnValues[1]);
runInfo.m_szPath[ServerManage::RunInfo::MAX_PATH_LEN - 1] = 0;
if(!runTable.insert(CManageClientManager::RunTable::value_type(
runInfo.m_dwPathID, runInfo)).second)
{
ERRLOG1(g_Log, "Insert failed. Key : %d", runInfo.m_dwPathID);
}
}
return 0;
}
int GetOptionInfoCallback(void *callBackArg, int nColumnNum,
char **szColumnValues, char **szColumnNames)
{
if(2 == nColumnNum)
{
CManageClientManager::RunTable& runTable =
*reinterpret_cast<CManageClientManager::RunTable*>(callBackArg);
ServerManage::RunInfo runInfo;
memset(&runInfo, 0, sizeof(ServerManage::RunInfo));
runInfo.m_dwOptionID = atol(szColumnValues[0]);
_snprintf(runInfo.m_szOption, ServerManage::RunInfo::MAX_OPT_LEN - 1,
"%s", szColumnValues[1]);
runInfo.m_szOption[ServerManage::RunInfo::MAX_OPT_LEN - 1] = 0;
if(!runTable.insert(CManageClientManager::RunTable::value_type(
runInfo.m_dwOptionID, runInfo)).second)
{
ERRLOG1(g_Log, "Insert failed. Key : %d", runInfo.m_dwOptionID);
}
}
return 0;
}
int GetRunInfoCallback(void *callBackArg, int nColumnNum,
char **szColumnValues, char **szColumnNames)
{
if(4 == nColumnNum)
{
CManageClientManager::RunTable& runTable =
*reinterpret_cast<CManageClientManager::RunTable*>(callBackArg);
ServerManage::RunInfo runInfo;
memset(&runInfo, 0, sizeof(ServerManage::RunInfo));
runInfo.m_dwRunID = atol(szColumnValues[0]);
runInfo.m_dwPathID = atol(szColumnValues[1]);
runInfo.m_dwOptionID = atol(szColumnValues[2]);
runInfo.m_dwServerIP = atol(szColumnValues[3]);
if(!runTable.insert(CManageClientManager::RunTable::value_type(
runInfo.m_dwRunID, runInfo)).second)
{
ERRLOG1(g_Log, "Insert failed. Key : %d", runInfo.m_dwOptionID);
}
}
return 0;
}
bool CManageClientManager::Get(InfoType eInfoType, RunTable& runTable)
{
runTable.clear();
const char* szQuery = 0;
CSQLite::QueryCallBack lpQueryCallBack = 0;
switch(eInfoType)
{
case SERVER_INFO:
szQuery = "SELECT IP, ServerName FROM TblServerInfo";
lpQueryCallBack = GetServerInfoCallback;
break;
case RUN_PATH_INFO:
szQuery = "SELECT PathID, RunPath FROM TblRunPath";
lpQueryCallBack = GetPathInfoCallback;
break;
case OPTION_INFO:
szQuery = "SELECT OptionID, RunOption FROM TblRunOptions";
lpQueryCallBack = GetOptionInfoCallback;
break;
case RUN_INFO:
szQuery = "SELECT RunID, PathID, OptionID, ServerIP FROM TblRunInfo";
lpQueryCallBack = GetRunInfoCallback;
break;
default:
ERRLOG1(g_Log, "Unknown InfoType : %d", eInfoType);
return false;
};
if(!m_ManageServerDB.GetSQLite().ExecuteQuery(szQuery, lpQueryCallBack, &runTable))
{
const char* szError = m_ManageServerDB.GetSQLite().GetLastError();
if(0 != szError)
{
ERRLOG2(g_Log, "Query failed : refresh runinfo failed : %s(Query:%s)",
szError, szQuery);
}
return false;
}
return true;
}
// ----------------------------------------------------------------------------------------------
// 실행 정보 얻어오기
bool CManageClientManager::GetRunInfo(ServerManage::RunInfo* lpRunInfo_Out, size_t* nArrayNum_InOut)
{
size_t nRunTableSize = m_RunTable.size();
if(0 != lpRunInfo_Out && 0 != nArrayNum_InOut && nRunTableSize <= *nArrayNum_InOut)
{
RunTable::iterator pos = m_RunTable.begin();
RunTable::iterator end = m_RunTable.end();
for(; pos != end; ++pos, ++lpRunInfo_Out)
{
*lpRunInfo_Out = pos->second;
}
*nArrayNum_InOut = nRunTableSize;
return true;
}
return false;
}
bool CManageClientManager::GetRunInfo(unsigned long dwRunID, ServerManage::RunInfo& runInfo_Out)
{
RunTable::iterator pos = m_RunTable.find(dwRunID);
if(pos != m_RunTable.end())
{
runInfo_Out = pos->second;
return true;
}
return false;
}
bool CManageClientManager::HasRunInfo(unsigned long dwRunID)
{
return m_RunTable.find(dwRunID) != m_RunTable.end();
}
void CManageClientManager::GetRunInfoFromIP(unsigned long dwServerIP, RunTable& runTable)
{
RunTable::iterator pos = m_RunTable.begin();
RunTable::iterator end = m_RunTable.end();
for(; pos != end; ++pos)
{
RunTable::value_type& data = *pos;
if(data.second.m_dwServerIP == dwServerIP)
{
runTable.insert(data);
}
}
}
int ReloadRunInfoCallback(void *callBackArg, int nColumnNum, char **szColumnValues, char **szColumnNames)
{
CManageClientManager::RunTable& runTable =
*reinterpret_cast<CManageClientManager::RunTable*>(callBackArg);
if(7 == nColumnNum)
{
ServerManage::RunInfo runInfo;
memset(&runInfo, 0, sizeof(ServerManage::RunInfo));
runInfo.m_dwRunID = atol(szColumnValues[0]);
runInfo.m_dwServerIP = atol(szColumnValues[1]);
runInfo.m_dwPathID = atol(szColumnValues[2]);
runInfo.m_dwOptionID = atol(szColumnValues[3]);
_snprintf(runInfo.m_szServerName, ServerManage::RunInfo::MAX_SERVER_NAME - 1,
"%s", szColumnValues[4]);
runInfo.m_szServerName[ServerManage::RunInfo::MAX_SERVER_NAME - 1] = 0;
_snprintf(runInfo.m_szPath, ServerManage::RunInfo::MAX_PATH_LEN - 1,
"%s", szColumnValues[5]);
runInfo.m_szPath[ServerManage::RunInfo::MAX_PATH_LEN - 1] = 0;
_snprintf(runInfo.m_szOption, ServerManage::RunInfo::MAX_OPT_LEN - 1,
"%s", szColumnValues[6]);
runInfo.m_szOption[ServerManage::RunInfo::MAX_OPT_LEN - 1] = 0;
if(!runTable.insert(CManageClientManager::RunTable::value_type(
atol(szColumnValues[0]), runInfo)).second)
{
ERRLOG0(g_Log, "Reload failed");
}
}
return 0;
}
bool CManageClientManager::ReloadRunInfo()
{
m_RunTable.clear();
const char* szQuery = "SELECT TblRunInfo.RunID, TblRunInfo.ServerIP, TblRunInfo.PathID, "
"TblRunInfo.OptionID, TblServerInfo.ServerName, TblRunPath.RunPath, TblRunOptions.RunOption "
"FROM TblRunInfo "
"LEFT OUTER JOIN TblRunPath ON TblRunInfo.PathID = TblRunPath.PathID "
"LEFT OUTER JOIN TblRunOptions ON TblRunInfo.OptionID = TblRunOptions.OptionID "
"LEFT OUTER JOIN TblServerInfo ON TblRunInfo.ServerIP = TblServerInfo.IP ";
if(!m_ManageServerDB.GetSQLite().ExecuteQuery(szQuery, ReloadRunInfoCallback, &m_RunTable))
{
const char* szError = m_ManageServerDB.GetSQLite().GetLastError();
if(0 != szError)
{
ERRLOG2(g_Log, "Query failed : refresh runinfo failed : %s(Query:%s)",
szError, szQuery);
}
return false;
}
return true;
}

View File

@@ -0,0 +1,84 @@
#ifndef _CUSTOM_MANAGE_CLIENT_MANAGER_H_
#define _CUSTOM_MANAGE_CLIENT_MANAGER_H_
#pragma warning(disable:4800)
#include <winsock2.h>
#include <windows.h>
#include <map>
#include <boost/pool/pool_alloc.hpp>
#include <Network/Packet/ManagePacketCmd.h>
// forward decl.
class CSession;
class CManageServerDB;
class CManageClientManager
{
public:
typedef std::map<unsigned long, ServerManage::RunInfo, std::less<unsigned long>,
boost::pool_allocator<std::pair<unsigned long, ServerManage::RunInfo> > > RunTable;
enum
{
MAX_RUNID = 0xFFFFFFFF
};
enum InfoType
{
SERVER_INFO,
RUN_PATH_INFO,
OPTION_INFO,
RUN_INFO
};
static CManageClientManager& GetInstance();
static bool SendRunInfo(CSession& Session, const RunTable& runTable);
// ----------------------------------------------------------------------------------------------
// 서버 정보 관련
bool Add(InfoType eInfoType, const ServerManage::RunInfo& runInfo, unsigned long& dwID_Out);
bool Modify(InfoType eInfoType, const ServerManage::RunInfo& runInfo);
bool Remove(InfoType eInfoType, unsigned long dwID, bool bDeleteRelated);
bool Get(InfoType eInfoType, RunTable& runTable);
// ----------------------------------------------------------------------------------------------
// 실행 정보 얻어오기
bool GetRunInfo(ServerManage::RunInfo* lpRunInfo_Out, size_t* nArrayNum_InOut);
bool GetRunInfo(unsigned long dwRunID, ServerManage::RunInfo& runInfo_Out);
bool HasRunInfo(unsigned long dwRunID);
void GetRunInfoFromIP(unsigned long dwServerIP, RunTable& runTable);
const RunTable& GetRunInfoTable() const { return m_RunTable; }
size_t GetRunInfoNum() { return m_RunTable.size(); }
template<typename FnProcess>
void EnumRunInfo(FnProcess fnProcess)
{
RunTable::const_iterator pos = m_RunTable.begin();
RunTable::const_iterator end = m_RunTable.end();
for(;pos != end; ++pos)
{
fnProcess(pos->second);
}
}
bool ReloadRunInfo();
private:
CManageClientManager(CManageServerDB& manageServerDB);
~CManageClientManager();
CManageServerDB& m_ManageServerDB;
RunTable m_RunTable;
};
#endif

View File

@@ -0,0 +1,69 @@
#include "stdafx.h"
#include "ManageClientManager.h"
#include <Network/Session/Session.h>
#include <Network/Dispatch/SendManagePacket.h>
#include <Log/ServerLog.h>
bool CManageClientManager::SendRunInfo(CSession& Session, const RunTable& runTable)
{
if(!runTable.empty())
{
CManageClientManager::RunTable::const_iterator pos = runTable.begin();
CManageClientManager::RunTable::const_iterator end = runTable.end();
const int MAX_RUN_INFO = (PktMaxLen - sizeof(ServerManage::ManageCommand)) / sizeof(ServerManage::RunInfo);
ServerManage::RunInfo tempRunInfo[MAX_RUN_INFO];
if(!ServerManage::SendManagePacket(Session, ServerManage::CMD::UpdateRunList,
0, 0, 0, 0, 0, ServerManage::SEND_RUNINFO_START, 0, 0))
{
ERRLOG1(g_Log, "SS:0x%p/UpdateRunList : SendRunInfoStart packet failed", &Session);
return false;
}
int nRunInfo = 0;
for(;pos != end; ++pos)
{
tempRunInfo[nRunInfo] = pos->second;
++nRunInfo;
if(nRunInfo == MAX_RUN_INFO)
{
if(!ServerManage::SendManagePacket(Session,
ServerManage::CMD::UpdateRunList,
0, 0, 0, 0, nRunInfo * sizeof(ServerManage::RunInfo),
ServerManage::SEND_RUNINFO_NOW, tempRunInfo, 0))
{
ERRLOG1(g_Log, "SS:0x%p/UpdateRunList : SendRunInfoNow packet failed", &Session);
return false;
}
nRunInfo = 0;
}
}
if(0 < nRunInfo)
{
if(!ServerManage::SendManagePacket(Session, ServerManage::CMD::UpdateRunList,
0, 0, 0, 0, nRunInfo * sizeof(ServerManage::RunInfo),
ServerManage::SEND_RUNINFO_NOW, tempRunInfo, 0))
{
ERRLOG1(g_Log, "SS:0x%p/UpdateRunList : SendRunInfoNow packet failed", &Session);
return false;
}
}
if(!ServerManage::SendManagePacket(Session, ServerManage::CMD::UpdateRunList,
0, 0, 0, 0, 0, ServerManage::SEND_RUNINFO_FINISH, 0, 0))
{
ERRLOG1(g_Log, "SS:0x%p/UpdateRunList : SendRunInfoFinish packet failed", &Session);
return false;
}
}
return true;
}

View File

@@ -0,0 +1,219 @@
#include "stdafx.h"
#include "RylServerBindRunID.h"
#include <Log/ServerLog.h>
#include <ServerManage/ManageClientManager.h>
CRylServerBindRunID& CRylServerBindRunID::GetInstance()
{
static CRylServerBindRunID bindRunID;
return bindRunID;
}
CRylServerBindRunID::CRylServerBindRunID()
{
_sntprintf(m_szDefaultSetupFileName, MAX_PATH - 1, "%s",
_T("./RylSetupBindServerID.ini"));
m_szDefaultSetupFileName[MAX_PATH - 1] = 0;
Load();
}
CRylServerBindRunID::~CRylServerBindRunID()
{
}
bool CRylServerBindRunID::SetID(unsigned long dwRunID, unsigned long dwServerID)
{
std::pair<BindIDTable::iterator, bool> runIDpair =
m_RunID.insert(BindIDTable::value_type(dwRunID, dwServerID));
if(runIDpair.second)
{
std::pair<BindIDTable::iterator, bool> serverIDPair =
m_ServerID.insert(BindIDTable::value_type(dwServerID, dwRunID));
if(serverIDPair.second)
{
return true;
}
m_RunID.erase(runIDpair.first);
}
return false;
}
bool CRylServerBindRunID::RemoveFromRunID(unsigned long dwRunID)
{
BindIDTable::iterator pos_runID = m_RunID.find(dwRunID);
if(pos_runID != m_RunID.end())
{
unsigned long dwServerID = pos_runID->second;
BindIDTable::iterator pos_serverID = m_ServerID.find(dwServerID);
if(pos_serverID != m_ServerID.end())
{
m_RunID.erase(pos_runID);
m_ServerID.erase(pos_serverID);
return true;
}
}
return false;
}
bool CRylServerBindRunID::RemoveFromServerID(unsigned long dwServerID)
{
BindIDTable::iterator pos_serverID = m_ServerID.find(dwServerID);
if(pos_serverID != m_ServerID.end())
{
unsigned long dwRunID = pos_serverID->second;
BindIDTable::iterator pos_runID = m_RunID.find(dwRunID);
if(pos_runID != m_RunID.end())
{
m_RunID.erase(pos_runID);
m_ServerID.erase(pos_serverID);
return true;
}
}
return false;
}
bool CRylServerBindRunID::GetRunID(unsigned long dwServerID, unsigned long* lpdwRunID)
{
BindIDTable::iterator pos = m_ServerID.find(dwServerID);
if(0 != lpdwRunID && pos != m_ServerID.end())
{
*lpdwRunID = pos->second;
return true;
}
return false;
}
bool CRylServerBindRunID::GetServerID(unsigned long dwRunID, unsigned long* lpdwServerID)
{
BindIDTable::iterator pos = m_RunID.find(dwRunID);
if(0 != lpdwServerID && pos != m_RunID.end())
{
*lpdwServerID = pos->second;
return true;
}
return false;
}
void CRylServerBindRunID::SetSetupFileName(const TCHAR* szSetupFileName)
{
if(0 != szSetupFileName)
{
_sntprintf(m_szDefaultSetupFileName, MAX_PATH - 1, "%s", szSetupFileName);
m_szDefaultSetupFileName[MAX_PATH - 1] = 0;
}
}
bool CRylServerBindRunID::Load()
{
HANDLE hFile = CreateFile(m_szDefaultSetupFileName,
GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
unsigned long dwWritten = 0;
bool bResult = false;
if(INVALID_HANDLE_VALUE != hFile)
{
size_t nBindIDNum = 0;
m_RunID.clear();
m_ServerID.clear();
if(ReadFile(hFile, &nBindIDNum, sizeof(size_t), &dwWritten, 0))
{
BindID bindID;
for(size_t nCount = 0; nCount < nBindIDNum; ++nCount)
{
if(ReadFile(hFile, &bindID, sizeof(BindID), &dwWritten, 0))
{
m_RunID.insert(bindID);
std::swap(bindID.first, bindID.second);
m_ServerID.insert(bindID);
}
else
{
break;
}
}
if(nCount == nBindIDNum)
{
bResult = true;
}
}
CloseHandle(hFile);
};
return bResult;
}
bool CRylServerBindRunID::Save()
{
HANDLE hFile = CreateFile(m_szDefaultSetupFileName,
GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
unsigned long dwWritten = 0;
bool bResult = false;
if(INVALID_HANDLE_VALUE != hFile)
{
size_t nBindIDNum = m_RunID.size();
if(WriteFile(hFile, &nBindIDNum, sizeof(size_t), &dwWritten, 0))
{
BindIDTable::iterator pos = m_RunID.begin();
BindIDTable::iterator end = m_RunID.end();
BindID bindID;
for(; pos != end; ++pos)
{
bindID = *pos;
if(!WriteFile(hFile, &bindID, sizeof(BindID), &dwWritten, 0))
{
break;
}
}
if(pos == end)
{
bResult = true;
}
}
CloseHandle(hFile);
};
return bResult;
}

View File

@@ -0,0 +1,61 @@
#ifndef _RYL_SERVER_BIND_RUN_ID_
#define _RYL_SERVER_BIND_RUN_ID_
#pragma warning(disable:4800)
#include <map>
#include <new>
#include <boost/pool/pool_alloc.hpp>
#include <tchar.h>
class CRylServerBindRunID
{
public:
static CRylServerBindRunID& GetInstance();
bool SetID(unsigned long dwRunID, unsigned long dwServerID);
bool RemoveFromRunID(unsigned long dwRunID);
bool RemoveFromServerID(unsigned long dwServerID);
bool GetRunID(unsigned long dwServerID, unsigned long* lpdwRunID);
bool GetServerID(unsigned long dwRunID, unsigned long* lpdwServerID);
void SetSetupFileName(const TCHAR* szSetupFileName);
bool Save();
bool Load();
template<typename FnProcess>
void EnumID(FnProcess fnProcess)
{
BindIDTable::iterator pos = m_RunID.begin();
BindIDTable::iterator end = m_RunID.end();
for(; pos != end; ++pos)
{
// first : RunID, Second : ServerID
fnProcess(pos->first, pos->second);
}
}
size_t GetPairNum() const { return m_RunID.size(); }
private:
typedef std::pair<unsigned long, unsigned long> BindID;
typedef std::map<unsigned long, unsigned long, std::less<unsigned long>,
boost::fast_pool_allocator<std::pair<unsigned long, unsigned long> > > BindIDTable;
CRylServerBindRunID();
~CRylServerBindRunID();
BindIDTable m_RunID; // key : RunID, value : ServerID
BindIDTable m_ServerID; // key : ServerID, value : RunID
TCHAR m_szDefaultSetupFileName[MAX_PATH];
};
#endif

View File

@@ -0,0 +1,156 @@
#include "stdafx.h"
#include "RylServerGroupSetup.h"
// forward decl.
void ReadRylServerStringValues(CRylServerGroupSetup::ServerStringMap& serverStringMap,
const char* szReadSection, const char* szKey, const char* szFileName);
void WriteRylServerStringValues(CRylServerGroupSetup::ServerStringMap& serverStringMap,
const char* szReadSection, const char* szKey, const char* szFileName);
CRylServerGroupSetup& CRylServerGroupSetup::GetInstance()
{
static CRylServerGroupSetup rylServerGroupSetup;
return rylServerGroupSetup;
}
CRylServerGroupSetup::CRylServerGroupSetup()
{
SetSetupFileName("./RylSetupServerGroup.ini");
Load();
}
CRylServerGroupSetup::~CRylServerGroupSetup()
{
}
const char* CRylServerGroupSetup::GetSetupString(SetupType eSetupType, unsigned long dwKey)
{
ServerStringMap::iterator pos;
ServerStringMap::iterator end;
switch(eSetupType)
{
case SERVER_GROUP: pos = m_ServerGroup.find(dwKey); end = m_ServerGroup.end(); break;
case SERVER_TYPE: pos = m_ServerType.find(dwKey); end = m_ServerType.end(); break;
case SERVER_ZONE: pos = m_ServerZone.find(dwKey); end = m_ServerZone.end(); break;
case SERVER_CHANNEL: pos = m_ServerChannel.find(dwKey); end = m_ServerChannel.end(); break;
default:
return 0;
}
return (pos != end) ? pos->second.c_str() : 0;
}
void CRylServerGroupSetup::Load(const char* szFileName)
{
m_ServerGroup.clear();
m_ServerType.clear();
m_ServerZone.clear();
m_ServerChannel.clear();
ReadRylServerStringValues(m_ServerGroup, "SERVER_GROUP", "SERVER_GROUP", szFileName);
ReadRylServerStringValues(m_ServerType, "SERVER_TYPE", "SERVER_TYPE", szFileName);
ReadRylServerStringValues(m_ServerZone, "GAMESERVER", "GAME_ZONE", szFileName);
ReadRylServerStringValues(m_ServerChannel, "GENERAL", "GAME_CHANNEL", szFileName);
}
void CRylServerGroupSetup::Save(const char* szFileName)
{
WriteRylServerStringValues(m_ServerGroup, "SERVER_GROUP", "SERVER_GROUP", szFileName);
WriteRylServerStringValues(m_ServerType, "SERVER_TYPE", "SERVER_TYPE", szFileName);
WriteRylServerStringValues(m_ServerZone, "GAMESERVER", "GAME_ZONE", szFileName);
WriteRylServerStringValues(m_ServerChannel, "GENERAL", "GAME_CHANNEL", szFileName);
}
void CRylServerGroupSetup::SetSetupFileName(const char* szFileName)
{
if(0 != szFileName)
{
_snprintf(m_szSetupFileName, MAX_PATH - 1, "%s", szFileName);
m_szSetupFileName[MAX_PATH - 1] = 0;
}
}
unsigned long CRylServerGroupSetup::GetStringNum(SetupType eSetupType)
{
switch(eSetupType)
{
case SERVER_GROUP: return m_ServerGroup.size();
case SERVER_TYPE: return m_ServerType.size();
case SERVER_ZONE: return m_ServerZone.size();
case SERVER_CHANNEL: return m_ServerChannel.size();
}
return 0;
}
void ReadRylServerStringValues(CRylServerGroupSetup::ServerStringMap& serverStringMap,
const char* szReadSection, const char* szKey, const char* szFileName)
{
char szNumKey[MAX_PATH];
char szStringKey[MAX_PATH];
char szStringValue[MAX_PATH];
unsigned long dwKey = 0;
const unsigned long dwInvalidKey = 0xFFFFFFFF;
_snprintf(szStringKey, MAX_PATH - 1, "%s_NUM", szKey);
UINT nNum = GetPrivateProfileInt(szReadSection, szStringKey, 0, szFileName);
for(UINT nIndex = 0; nIndex < nNum; ++nIndex)
{
_snprintf(szNumKey, MAX_PATH - 1, "%s_KEY%d", szKey, nIndex);
_snprintf(szStringKey, MAX_PATH - 1, "%s_STRING%d", szKey, nIndex);
dwKey = static_cast<unsigned long>(GetPrivateProfileInt(szReadSection,
szNumKey, dwInvalidKey, szFileName));
GetPrivateProfileString(szReadSection, szStringKey, "",
szStringValue, MAX_PATH, szFileName);
if(dwKey != dwInvalidKey && 0 != szStringValue[0])
{
serverStringMap.insert(CRylServerGroupSetup::ServerStringMap::value_type(dwKey, szStringValue));
}
}
}
void WriteRylServerStringValues(CRylServerGroupSetup::ServerStringMap& serverStringMap,
const char* szReadSection, const char* szKey, const char* szFileName)
{
char szNumKey[MAX_PATH];
char szNumValue[MAX_PATH];
char szStringKey[MAX_PATH];
char szStringValue[MAX_PATH];
CRylServerGroupSetup::ServerStringMap::iterator pos = serverStringMap.begin();
CRylServerGroupSetup::ServerStringMap::iterator end = serverStringMap.end();
UINT nIndex = 0;
for(;pos != end; ++pos, ++nIndex)
{
CRylServerGroupSetup::ServerStringMap::value_type& value = *pos;
_snprintf(szNumKey, MAX_PATH - 1, "%s_KEY%d", szKey, nIndex);
_snprintf(szStringKey, MAX_PATH - 1, "%s_STRING%d", szKey, nIndex);
_snprintf(szNumValue, MAX_PATH - 1, "%d", value.first);
WritePrivateProfileString(szReadSection, szNumKey, szNumValue, szFileName);
WritePrivateProfileString(szReadSection, szStringKey, value.second.c_str(), szFileName);
}
_snprintf(szStringKey, MAX_PATH - 1, "%s_NUM", szKey);
_snprintf(szStringValue, MAX_PATH - 1, "%d", serverStringMap.size());
WritePrivateProfileString(szReadSection, szStringKey, szStringValue, szFileName);
}

View File

@@ -0,0 +1,77 @@
#ifndef _RYL_SERVER_GROUP_SETUP_H_
#define _RYL_SERVER_GROUP_SETUP_H_
#pragma warning(disable:4800)
#include <map>
#include <string>
#include <boost/pool/pool_alloc.hpp>
class CRylServerGroupSetup
{
public:
typedef std::basic_string<char, std::char_traits<char>, boost::pool_allocator<char> >
boost_string;
typedef std::map<unsigned long, boost_string, std::less<unsigned long>,
boost::pool_allocator<std::pair<unsigned long, boost_string> > >
ServerStringMap;
enum SetupType
{
SERVER_GROUP,
SERVER_TYPE,
SERVER_ZONE,
SERVER_CHANNEL
};
static CRylServerGroupSetup& GetInstance();
const char* GetSetupString(SetupType eSetupType, unsigned long dwKey);
unsigned long GetStringNum(SetupType eSetupType);
void Load(const char* szFileName = GetInstance().GetSetupFileName());
void Save(const char* szFileName = GetInstance().GetSetupFileName());
void SetSetupFileName(const char* szFileName);
const char* GetSetupFileName() { return m_szSetupFileName; }
template<typename FnProcess>
void EnumSetup(SetupType eSetupType, FnProcess fnProcess)
{
ServerStringMap::iterator pos;
ServerStringMap::iterator end;
switch(eSetupType)
{
case SERVER_GROUP: pos = m_ServerGroup.begin(); end = m_ServerGroup.end(); break;
case SERVER_TYPE: pos = m_ServerType.begin(); end = m_ServerType.end(); break;
case SERVER_ZONE: pos = m_ServerZone.begin(); end = m_ServerZone.end(); break;
case SERVER_CHANNEL: pos = m_ServerChannel.begin(); end = m_ServerChannel.end(); break;
default:
return;
}
for(; pos != end; ++pos)
{
ServerStringMap::value_type& value = *pos;
fnProcess(value.first, value.second.c_str());
}
}
private:
CRylServerGroupSetup();
~CRylServerGroupSetup();
ServerStringMap m_ServerGroup;
ServerStringMap m_ServerType;
ServerStringMap m_ServerZone;
ServerStringMap m_ServerChannel;
char m_szSetupFileName[MAX_PATH];
};
#endif

View File

@@ -0,0 +1,95 @@
#include "stdafx.h"
#include "SetupClient.h"
#include <cstdio>
#include <Utility/Setup/ServerSetup.h>
ManageSetup::ClientSetup::ClientSetup()
{
SetSetupFileName("./ManageSetupClient.ini");
Load();
}
ManageSetup::ClientSetup::~ClientSetup()
{
}
ManageSetup::ClientSetup& ManageSetup::ClientSetup::GetInstance()
{
static ClientSetup clientSetup;
return clientSetup;
}
void ManageSetup::ClientSetup::Load(const char* szSetupFileName)
{
char szIP[MAX_PATH];
GetPrivateProfileString("ManageClient", "ManageServerIP", 0, szIP, MAX_PATH, szSetupFileName);
UINT nPort = GetPrivateProfileInt("ManageClient", "ManageServerPort",
CServerSetup::ManageServerManageClientListen, szSetupFileName);
m_ManageServerAddr.set_addr(szIP, static_cast<unsigned short>(nPort));
}
void ManageSetup::ClientSetup::Save(const char* szSetupFileName)
{
char szIP[MAX_PATH];
_snprintf(szIP, MAX_PATH - 1, "%s", m_ManageServerAddr.get_addr_string());
szIP[MAX_PATH - 1] = 0;
char szPort[MAX_PATH];
_snprintf(szPort, MAX_PATH - 1, "%d", m_ManageServerAddr.get_port_in());
szPort[MAX_PATH - 1] = 0;
WritePrivateProfileString("ManageClient", "ManageServerIP", szIP, szSetupFileName);
WritePrivateProfileString("ManageClient", "ManageServerPort", szPort, szSetupFileName);
}
void ManageSetup::ClientSetup::SetSetupFileName(const char* szSetupFileName)
{
if(0 != szSetupFileName)
{
_snprintf(m_szSetupFileName, MAX_PATH, "%s", szSetupFileName);
m_szSetupFileName[MAX_PATH - 1] = 0;
}
}
bool ManageSetup::ClientSetup::SerializeIn(const char* szData_In, unsigned long dwDataLen_In)
{
if(dwDataLen_In == GetExpectedSerializedDataSize())
{
int nAddrSize = 0;
memcpy(&m_ManageServerAddr.get_addr(), szData_In, sizeof(sockaddr));
memcpy(&nAddrSize, szData_In + sizeof(sockaddr), sizeof(int));
m_ManageServerAddr.set_size(nAddrSize);
return true;
}
return false;
}
bool ManageSetup::ClientSetup::SerializeOut(char* szData_InOut, unsigned long& dwDataLen_InOut)
{
if(GetExpectedSerializedDataSize() < dwDataLen_InOut)
{
int nAddrSize = m_ManageServerAddr.get_size();
memcpy(szData_InOut, &m_ManageServerAddr.get_addr(), sizeof(sockaddr));
memcpy(szData_InOut + sizeof(sockaddr), &nAddrSize, sizeof(int));
dwDataLen_InOut = GetExpectedSerializedDataSize();
return true;
}
return false;
}
unsigned long ManageSetup::ClientSetup::GetExpectedSerializedDataSize()
{
return static_cast<unsigned long>(sizeof(sockaddr) + sizeof(int));
}

View File

@@ -0,0 +1,40 @@
#ifndef _GM_NETWORK_MANAGE_SETUP_CLIENT_H_
#define _GM_NETWORK_MANAGE_SETUP_CLIENT_H_
#include <Network/Address/INET_Addr.h>
namespace ManageSetup
{
class ClientSetup
{
public:
static ClientSetup& GetInstance();
bool SerializeIn(const char* szData_In, unsigned long dwDataLen_In);
bool SerializeOut(char* szData_InOut, unsigned long& dwDataLen_InOut);
unsigned long GetExpectedSerializedDataSize();
void Load(const char* szSetupFileName = ClientSetup::GetInstance().GetSetupFileName());
void Save(const char* szSetupFileName = ClientSetup::GetInstance().GetSetupFileName());
const char* GetSetupFileName() { return m_szSetupFileName; }
void SetSetupFileName(const char* szSetupFileName);
INET_Addr& GetManageServerAddr() { return m_ManageServerAddr; }
private:
ClientSetup();
~ClientSetup();
INET_Addr m_ManageServerAddr;
char m_szSetupFileName[MAX_PATH];
};
};
#endif

View File

@@ -0,0 +1,543 @@
#include "stdafx.h"
#include "ToolUserManageTable.h"
#include <tchar.h>
#include <Log/ServerLog.h>
#include <Stream/Buffer/Buffer.h>
#include <Stream/Buffer/BufferFactory.h>
#include <Network/Session/Session.h>
#include <Network/Dispatch/SendManagePacket.h>
#include <Network/Dispatch/ManageServer/ManageToolServerDispatch.h>
#include <DB/SQLite.h>
#include <DB/ManageServerDB.h>
#include <Setup/RylServerGroupSetup.h>
CToolUserManager& CToolUserManager::GetInstance()
{
static CToolUserManager toolUserManager(CManageServerDB::GetInstance());
return toolUserManager;
}
inline void SetUserInfo(ServerManage::UserInfo& UserInfo_Out,
const char* szID, const char* szPass,
const char* szFullName, const char* szIP,
const char* szAdminLevel)
{
_snprintf(UserInfo_Out.szID, ServerManage::UserInfo::ID_LEN - 1, "%s", szID);
UserInfo_Out.szID[ServerManage::UserInfo::ID_LEN - 1] = 0;
_snprintf(UserInfo_Out.szPassword, ServerManage::UserInfo::PASS_LEN - 1, "%s", szPass);
UserInfo_Out.szPassword[ServerManage::UserInfo::PASS_LEN - 1] = 0;
_snprintf(UserInfo_Out.szFullName, ServerManage::UserInfo::NAME_LEN - 1, "%s", szFullName);
UserInfo_Out.szFullName[ServerManage::UserInfo::NAME_LEN - 1] = 0;
UserInfo_Out.dwIP = inet_addr(szIP);
UserInfo_Out.usAdminLevel = atoi(szAdminLevel);
}
CToolUserManager::ToolUser::ToolUser(CManageToolServerDispatch* lpDispatch,
ServerManage::UserInfo& userInfo)
: m_lpDispatch(lpDispatch), m_UserInfo(userInfo)
{
}
CToolUserManager::ToolUser::ToolUser()
: m_lpDispatch(0)
{
memset(&m_UserInfo, 0, sizeof(ServerManage::UserInfo));
}
enum ToolUserConst
{
TOOLUSER_MAX_QUERY = 1024
};
CToolUserManager::CToolUserManager(CManageServerDB& ManageServerDB)
: m_ManageServerDB(ManageServerDB)
{
memset(&m_ManageUser, 0, sizeof(ServerManage::UserInfo));
}
CToolUserManager::~CToolUserManager()
{
}
// -------------------------------------------------------------------------
// UserManagement
bool CToolUserManager::AddUser(const ServerManage::UserInfo& userInfo)
{
char szQuery[TOOLUSER_MAX_QUERY];
in_addr addr;
addr.S_un.S_addr = userInfo.dwIP;
int nQueryLen = _snprintf(szQuery, TOOLUSER_MAX_QUERY - 1,
"INSERT INTO TblManageToolUser values('%s', '%s', '%s', '%s', %d)",
userInfo.szID, userInfo.szPassword, userInfo.szFullName,
inet_ntoa(addr), userInfo.usAdminLevel);
szQuery[TOOLUSER_MAX_QUERY - 1] = 0;
if(0 < nQueryLen)
{
CSQLite::Dataset addUserQuery(m_ManageServerDB.GetSQLite(), szQuery);
if(addUserQuery.Compile() && addUserQuery.Execute())
{
return true;
}
ERRLOG2(g_Log, "AddUser failed - query failed : %s(Query:%s)",
addUserQuery.GetLastError(), szQuery);
}
else
{
ERRLOG1(g_Log, "AddUser failed - make query failed : (Query:%s)", szQuery);
}
return false;
}
bool CToolUserManager::GetUserInfo(const char* szID_In,
ServerManage::UserInfo& userInfo_Out)
{
char szQuery[TOOLUSER_MAX_QUERY];
int nQueryLen = _snprintf(szQuery, TOOLUSER_MAX_QUERY - 1,
"SELECT ID, PASS, NAME, IP, LEVEL FROM TblManageToolUser WHERE ID = '%s'", szID_In);
szQuery[TOOLUSER_MAX_QUERY - 1] = 0;
if(0 < nQueryLen)
{
CSQLite::Dataset getUserQuery(m_ManageServerDB.GetSQLite(), szQuery);
int nColNum = 0;
const char** pazValue = 0;
const char** pazColumn = 0;
if(getUserQuery.Compile() &&
getUserQuery.Execute(&nColNum, &pazValue, &pazColumn))
{
if(5 == nColNum && 0 != pazValue)
{
SetUserInfo(userInfo_Out, pazValue[0], pazValue[1],
pazValue[2], pazValue[3], pazValue[4]);
return true;
}
}
ERRLOG2(g_Log, "Getuser failed - query error : %s(Query:%s)",
getUserQuery.GetLastError(), szQuery);
}
else
{
ERRLOG1(g_Log, "Getuser failed - create query failed : (Query:%s)", szQuery);
}
return false;
}
bool CToolUserManager::DelUser(const char* szID)
{
char szQuery[TOOLUSER_MAX_QUERY];
int nQueryLen = _snprintf(szQuery, TOOLUSER_MAX_QUERY - 1,
"DELETE FROM TblManageToolUser WHERE ID = '%s'", szID);
szQuery[TOOLUSER_MAX_QUERY - 1] = 0;
if(0 < nQueryLen)
{
CSQLite::Dataset delUserQuery(m_ManageServerDB.GetSQLite(), szQuery);
if(delUserQuery.Compile() && delUserQuery.Execute())
{
return true;
}
ERRLOG2(g_Log, "Deluser failed - query error : %s(Query:%s)",
delUserQuery.GetLastError(), szQuery);
}
else
{
ERRLOG1(g_Log, "Deluser failed - create query error : %s", szQuery);
}
return false;
}
bool CToolUserManager::ModifyUser(const ServerManage::UserInfo& modified)
{
char szQuery[TOOLUSER_MAX_QUERY];
in_addr addr;
addr.S_un.S_addr = modified.dwIP;
int nQueryLen = _snprintf(szQuery, TOOLUSER_MAX_QUERY - 1,
"UPDATE TblManageToolUser SET PASS = '%s', NAME = '%s', IP = '%s', LEVEL = %d WHERE ID = '%s'",
modified.szPassword, modified.szFullName, inet_ntoa(addr),
modified.usAdminLevel, modified.szID);
szQuery[TOOLUSER_MAX_QUERY - 1] = 0;
if(0 < nQueryLen)
{
CSQLite::Dataset modUserQuery(m_ManageServerDB.GetSQLite(), szQuery);
if(modUserQuery.Compile() && modUserQuery.Execute())
{
return true;
}
ERRLOG2(g_Log, "Moduser failed - query error : %s(Query:%s)",
modUserQuery.GetLastError(), szQuery);
}
else
{
ERRLOG1(g_Log, "Moduser failed - create query error : %s", szQuery);
}
return false;
}
bool CToolUserManager::SendAllUserInfo(CSession& Session)
{
const int MAX_USER_INFO = (PktMaxLen - sizeof(ServerManage::UserCommand)) / sizeof(ServerManage::UserInfo);
ServerManage::UserInfo tempUserInfo[MAX_USER_INFO];
CBufferFactory& bufferFactory = Session.GetPolicy().GetBufferFactory();
const char* szQuery = "SELECT ID, PASS, NAME, IP, LEVEL FROM TblManageToolUser";
CSQLite::Dataset getUserQuery(m_ManageServerDB.GetSQLite(), szQuery);
if(getUserQuery.Compile())
{
int nColNum = 0;
const char** pazValue = 0;
const char** pazColumn = 0;
int nRowCount = 0;
while(getUserQuery.Execute(&nColNum, &pazValue, &pazColumn))
{
if(5 == nColNum && 0 != pazValue)
{
SetUserInfo(tempUserInfo[nRowCount], pazValue[0],
pazValue[1], pazValue[2], pazValue[3], pazValue[4]);
memset(tempUserInfo[nRowCount].szPassword, 0,
ServerManage::UserInfo::PASS_LEN);
++nRowCount;
}
if(nRowCount == MAX_USER_INFO)
{
ServerManage::SendUserInfo(bufferFactory, &Session, tempUserInfo,
nRowCount, ServerManage::CMD::UserList, 0);
nRowCount = 0;
}
}
if(0 < nRowCount)
{
ServerManage::SendUserInfo(bufferFactory, &Session, tempUserInfo,
nRowCount, ServerManage::CMD::UserList, 0);
}
if(0 != getUserQuery.GetLastError())
{
ERRLOG2(g_Log, "Getuser failed - query error : %s(Query:%s)",
getUserQuery.GetLastError(), szQuery);
}
}
else if(0 != getUserQuery.GetLastError())
{
ERRLOG2(g_Log, "Getuser failed - compile query failed : %s(Query:%s)",
getUserQuery.GetLastError(), szQuery);
}
return true;
}
bool CToolUserManager::GetUserInfo(UserList& userList_Out)
{
const unsigned char MAX_USER_INFO = 100;
ServerManage::UserInfo tempUserInfo[MAX_USER_INFO];
const char* szQuery = "SELECT ID, PASS, NAME, IP, LEVEL FROM TblManageToolUser";
CSQLite::Dataset getUserQuery(m_ManageServerDB.GetSQLite(), szQuery);
if(getUserQuery.Compile())
{
int nColNum = 0;
const char** pazValue = 0;
const char** pazColumn = 0;
int nRowCount = 0;
while(getUserQuery.Execute(&nColNum, &pazValue, &pazColumn))
{
if(5 == nColNum && 0 != pazValue)
{
SetUserInfo(tempUserInfo[nRowCount], pazValue[0],
pazValue[1], pazValue[2], pazValue[3], pazValue[4]);
++nRowCount;
}
if(nRowCount == MAX_USER_INFO)
{
userList_Out.insert(userList_Out.end(), tempUserInfo, tempUserInfo + nRowCount);
nRowCount = 0;
}
}
if(0 < nRowCount)
{
userList_Out.insert(userList_Out.end(), tempUserInfo, tempUserInfo + nRowCount);
}
if(0 != getUserQuery.GetLastError())
{
ERRLOG2(g_Log, "Getuser failed - query error : %s(Query:%s)",
getUserQuery.GetLastError(), szQuery);
}
else
{
return true;
}
}
else if(0 != getUserQuery.GetLastError())
{
ERRLOG2(g_Log, "Getuser failed - compile query failed : %s(Query:%s)",
getUserQuery.GetLastError(), szQuery);
}
return false;
}
// Login/Logout
ServerManage::UserCommandError CToolUserManager::Authorize(CManageToolServerDispatch& dispatch,
ServerManage::UserInfo& userInfo_inout)
{
ServerManage::UserInfo foundUserInfo;
memset(&foundUserInfo, 0, sizeof(ServerManage::UserInfo));
ServerManage::UserCommandError eUserCommandErr = ServerManage::NO_USER_COMMAND_ERROR;
int iCheck =
GetPrivateProfileInt("SETTING", "USER_IP_CHECK", 1, CRylServerGroupSetup::GetInstance().GetSetupFileName());
if(IsLogin(userInfo_inout.szID))
{
eUserCommandErr = ServerManage::ALREADY_LOGINED;
}
else if(!GetUserInfo(userInfo_inout.szID, foundUserInfo))
{
eUserCommandErr = ServerManage::CANNOT_AUTHORIZE_NOT_USER;
}
else if(0 != strncmp(foundUserInfo.szPassword, userInfo_inout.szPassword,
ServerManage::UserInfo::PASS_LEN))
{
eUserCommandErr = ServerManage::CANNOT_AUTHORIZE_INVALID_PASSWORD;
}
else if((1 == iCheck) && (foundUserInfo.dwIP != userInfo_inout.dwIP))
{
eUserCommandErr = ServerManage::CANNOT_AUTHORIZE_INVALID_IPADDRESS;
}
else
{
// ID, Password°¡ °°´Ù. ÀÎÁõ ¼º°ø.
Logout(foundUserInfo.szID);
m_LoginUserList.push_back(ToolUser(&dispatch, foundUserInfo));
userInfo_inout = foundUserInfo;
}
return eUserCommandErr;
}
bool CToolUserManager::IsLogin(const char* szName)
{
CurrentUserList::iterator pos = m_LoginUserList.begin();
CurrentUserList::iterator end = m_LoginUserList.end();
for(; pos != end; ++pos)
{
ToolUser& toolUser = *pos;
if(0 == strncmp(toolUser.m_UserInfo.szID, szName, ServerManage::UserInfo::ID_LEN))
{
return true;
}
}
return false;
}
bool CToolUserManager::Logout(const char* szName)
{
CurrentUserList::iterator pos = m_LoginUserList.begin();
CurrentUserList::iterator end = m_LoginUserList.end();
int nEraseCount = 0;
for(; pos != end;)
{
ToolUser& toolUser = *pos;
if(0 == strncmp(toolUser.m_UserInfo.szID, szName, ServerManage::UserInfo::ID_LEN))
{
// Logout info¸¦ ÁØ´Ù.
ServerManage::SendUserInfo(toolUser.m_lpDispatch->GetBufferFactory(), 0,
&toolUser.m_UserInfo, 1, ServerManage::CMD::UserLogout, 0);
if(IsManageUser(toolUser.m_UserInfo))
{
memset(&m_ManageUser, 0, sizeof(ServerManage::UserInfo));
ServerManage::SendUserInfo(toolUser.m_lpDispatch->GetBufferFactory(), 0,
&m_ManageUser, 1, ServerManage::CMD::ManagerInfo, 0);
}
pos = m_LoginUserList.erase(pos);
++nEraseCount;
}
else
{
++pos;
}
}
return (0 < nEraseCount);
}
// Send packets to all users
bool CToolUserManager::SendToAllLoginUser(const char* szBuffer, unsigned short usBufferSize, unsigned char cCmd_In)
{
CurrentUserList::iterator pos = m_LoginUserList.begin();
CurrentUserList::iterator end = m_LoginUserList.end();
for(; pos != end; ++pos)
{
ToolUser& toolUser = *pos;
CManageToolServerDispatch* lpDispatch = toolUser.m_lpDispatch;
if(0 != lpDispatch)
{
lpDispatch->GetSendStream().PutBuffer(szBuffer, usBufferSize, cCmd_In);
}
}
return true;
}
bool CToolUserManager::SendAllLoginUserInfo(CSession& Session)
{
const unsigned char MAX_USER_INFO = 100;
ServerManage::UserInfo tempUserInfo[MAX_USER_INFO];
CBufferFactory& bufferFactory = Session.GetPolicy().GetBufferFactory();
CurrentUserList::iterator pos = m_LoginUserList.begin();
CurrentUserList::iterator end = m_LoginUserList.end();
unsigned char cSendNum = 0;
for(; pos != end; ++pos)
{
tempUserInfo[cSendNum] = pos->m_UserInfo;
memset(tempUserInfo[cSendNum].szPassword, 0, ServerManage::UserInfo::PASS_LEN);
++cSendNum;
if(cSendNum == MAX_USER_INFO)
{
ServerManage::SendUserInfo(bufferFactory, &Session,
tempUserInfo, cSendNum, ServerManage::CMD::UserLogin, 0);
cSendNum = 0;
}
}
if(0 < cSendNum)
{
ServerManage::SendUserInfo(bufferFactory, &Session,
tempUserInfo, cSendNum, ServerManage::CMD::UserLogin, 0);
}
return true;
}
CManageToolServerDispatch* CToolUserManager::GetUserDispatch(unsigned long dwIP)
{
CurrentUserList::iterator pos = m_LoginUserList.begin();
CurrentUserList::iterator end = m_LoginUserList.end();
for(; pos != end; ++pos)
{
ToolUser& toolUser = *pos;
if(toolUser.m_UserInfo.dwIP == dwIP)
{
return toolUser.m_lpDispatch;
}
}
return 0;
}
CManageToolServerDispatch* CToolUserManager::GetUserDispatch(const char* szID)
{
CurrentUserList::iterator pos = m_LoginUserList.begin();
CurrentUserList::iterator end = m_LoginUserList.end();
for(; pos != end; ++pos)
{
ToolUser& toolUser = *pos;
if(0 == strncmp(toolUser.m_UserInfo.szID, szID, ServerManage::UserInfo::ID_LEN))
{
return toolUser.m_lpDispatch;
}
}
return 0;
}
bool CToolUserManager::IsManageUser(const ServerManage::UserInfo& UserInfo)
{
if(0 == strncmp(m_ManageUser.szID, UserInfo.szID, ServerManage::UserInfo::ID_LEN))
{
return true;
}
return false;
}

Some files were not shown because too many files have changed in this diff Show More