iTimothy

君看一叶舟,出没风波里


  • 首页

  • 分类

  • 归档

  • 项目

  • 关于

ADO连接SQL的一般过程

发表于 2004-12-19 | 分类于 技术控 | | 阅读次数:
字数统计: 299 字 | 阅读时长 ≈ 1 分钟

void ADOConn::OnInitADOConn() { ::CoInitialize(NULL); // 初始化OLE/COM库环境 ,为访问ADO接口做准备

try { // 创建Connection对象 m_pConnection.CreateInstance(“ADODB.Connection”); // 设置连接字符串,必须是BSTR型或者_bstr_t类型 _bstr_t strConnect = “Provider=SQLOLEDB; Server=flyspider;Database=HrSys; uid=sa; pwd=;”; m_pConnection->Open(strConnect,””,””,adModeUnknown); } // 捕捉异常 catch(_com_error e) { // 显示错误信息 AfxMessageBox(e.Description()); } }

// 执行查询 _RecordsetPtr& ADOConn::GetRecordSet(_bstr_t bstrSQL) { try { // 连接数据库,如果Connection对象为空,则重新连接数据库 if(m_pConnection==NULL) OnInitADOConn(); // 创建记录集对象 m_pRecordset.CreateInstance(__uuidof(Recordset)); // 取得表中的记录 m_pRecordset->Open(bstrSQL,m_pConnection.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText); } // 捕捉异常 catch(_com_error e) { // 显示错误信息 AfxMessageBox(e.Description()); } // 返回记录集 return m_pRecordset; }

// 执行SQL语句,Insert Update _variant_t BOOL ADOConn::ExecuteSQL(_bstr_t bstrSQL) { //_variant_t RecordsAffected; try { // 是否已经连接数据库 if(m_pConnection == NULL) OnInitADOConn(); // Connection对象的Execute方法:(_bstr_t CommandText, // VARIANT * RecordsAffected, long Options ) // 其中CommandText是命令字串,通常是SQL命令。 // 参数RecordsAffected是操作完成后所影响的行数, // 参数Options表示CommandText的类型:adCmdText-文本命令;adCmdTable-表名 // adCmdProc-存储过程;adCmdUnknown-未知 m_pConnection->Execute(bstrSQL,NULL,adCmdText); return true; } catch(_com_error e) { AfxMessageBox(e.Description()); return false; } }

void ADOConn::ExitConnect() { // 关闭记录集和连接 if (m_pRecordset != NULL) m_pRecordset->Close(); m_pConnection->Close(); // 释放环境 ::CoUninitialize(); }

截获系统注销时候的消息

发表于 2004-12-15 | 分类于 技术控 | | 阅读次数:
字数统计: 57 字 | 阅读时长 ≈ 1 分钟

使用WH_CALLWNDPROC类型钩子,回调函数如下:

LRESULT CALLBACK MyProc(int code, WPARAM wParam, LPARAM lParam) { switch (((CWPSTRUCT)lParam)->message) { case WM_QUERYENDSESSION: { switch( ((CWPSTRUCT)lParam)->lParam ) { case ENDSESSION_LOGOFF: { FILE pFile = NULL; ((CWPSTRUCT)lParam)->message = 0; AfxMessageBox(TEXT(“log off”)); return 0; } break; } } } return ::CallNextHookEx(g_hMessage, code, wParam, lParam); }

判断是否为文件夹或者文件

发表于 2004-11-29 | 分类于 技术控 | | 阅读次数:
字数统计: 67 字 | 阅读时长 ≈ 1 分钟
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int IsDirectoryOrFile(CString strFileName)
{
strFileName.TrimLeft();
strFileName.TrimRight();

WIN32_FIND_DATA fd;
HANDLE hFind = ::FindFirstFile(strFileName,&fd;);
::FindClose(hFind);

//不存在同名的文件或文件夹
if (hFind == INVALID_HANDLE_VALUE)
{
return 0 ;
}
//判断是否为目录
else if (fd.dwFileAttributes&FILE;_ATTRIBUTE_DIRECTORY)
{
return 2 ;
}
else//判断为文件
{
return 1;
}
}

MyP2P V1.0 点对点聊天工具

发表于 2004-11-27 | 分类于 我的拙作 | | 阅读次数:
字数统计: 163 字 | 阅读时长 ≈ 1 分钟

这是一个利用CSocket类实现的一个基于TCP传输的聊天小工具。也是我的第一个聊天小软件,点对点通信,分为服务器端和客户端,没有用到什么新的技术,练手而已。呵呵。

说明:服务器先填入端口后,启动服务,然后客户端填入服务器端口和IP,连通后,即可开始实时聊天了。 Enter为快捷键,输入内容后按Enter键即可发送信息。

软件截图如下:

客户端

服务端

源代码下载: 点击下载此文件 应用程序下载: 点击下载此文件

Windows 任务管理器如何确定应用程序没有响应

发表于 2004-11-17 | 分类于 技术控 | | 阅读次数:
字数统计: 598 字 | 阅读时长 ≈ 2 分钟

最近参加的一个项目要求实现远程任务管理功能,也就是”Remote Task Manager”(RTM)。我把它与Windows NT的任务管理器进行了比较,发现标准的任务管理器显示应用程序的状态(正在运行或者没有响应)。标准的任务管理器发送(通过SendMessageTimeout函数)一个消息到主应用窗口,如果函数调用失败或者超时–则应用程序的状态就是”没有响应”,否则状态为”正在运行”。 但我发现还有一个更好的解决方法。本文将通过实例程序进行示范。这个方法的思路是通过调用User32.dll中一个未公开的函数来实现的。这个函数存在于Windows 9x和Windows NT/2000系统中,但在两个系统中的名字是不同的。Windows 9x系统中的名字为:IsHungThread,在Windows NT/2000系统中的名字为IsHungAppWindow。下面是它们的原型:

1
2
3
4
5
6
7
BOOL IsHungAppWindow (
HWND hWnd, // 主应用窗口句柄
);
和
BOOL IsHungThread (
DWORD dwThreadId, // 主应用窗口的线程ID
);

不幸的是,微软在User32.lib中没有提供这两个函数的输出。也就是说,这两个函数是未公开函数,如果要在程序中使用它们,则必须通过GetProcAddress和GetModuleHandle函数动态加载:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
typedef BOOL (WINAPI *PROCISHUNGAPPWINDOW) (HWND);
typedef BOOL (WINAPI *PROCISHUNGTHREAD) (DWORD);

PROCISHUNGAPPWINDOW IsHungAppWindow;
PROCISHUNGTHREAD IsHungThread;

HMODULE hUser32 = GetModuleHandle("user32");

IsHungAppWindow = (PROCISHUNGAPPWINDOW)
GetProcAddress(hUser32,"IsHungAppWindow");

IsHungThread = (PROCISHUNGTHREAD)
GetProcAddress(hUser32,"IsHungThread");


//////////////////


// ishung.cpp (Windows 95/98/NT/2000)
//
// This example will show you how you can obtain the current status
// of the application.
//
//
// (c)1999 Ashot Oganesyan K, SmartLine, Inc
// mailto:[email protected], http://www.protect-me.com, http://www.codepile.com

#include
#include


// User32!IsHungAppWindow (NT specific!)
//
// The function retrieves the status (running or not responding) of the
// specified application
//
// BOOL IsHungAppWindow(
// HWND hWnd, // handle to main app's window
// );
typedef BOOL (WINAPI *PROCISHUNGAPPWINDOW)(HWND);


// User32!IsHungThread (95/98 specific!)
//
// The function retrieves the status (running or not responding) of the
// specified thread
//
// BOOL IsHungThread(
// DWORD dwThreadId, // The identifier of the main app's window thread
// );
typedef BOOL (WINAPI *PROCISHUNGTHREAD)(DWORD);


PROCISHUNGAPPWINDOW IsHungAppWindow;
PROCISHUNGTHREAD IsHungThread;


void main(int argc, char* argv[])
{
/* if (argc<2)
{
printf("Usage:\n\nishung.exe hWnd\n");
return;
}
*/
// HWND hWnd;
// sscanf(argv[1],"%lx",&hWnd;);

HWND hWnd = ::FindWindow(NULL, "CLENT");
if (hWnd == NULL)
{
printf("Incorrect window handle(handle is NULL)\n");
return;

}

if (!IsWindow(hWnd))
{
printf("Incorrect window handle\n");
return;
}

HMODULE hUser32 = GetModuleHandle("user32");
if (!hUser32)
return;

IsHungAppWindow = (PROCISHUNGAPPWINDOW)
GetProcAddress( hUser32,
"IsHungAppWindow" );

IsHungThread = (PROCISHUNGTHREAD) GetProcAddress( hUser32,
"IsHungThread" );

if (!IsHungAppWindow && !IsHungThread)
return;

OSVERSIONINFO osver;
osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (!GetVersionEx(&osver;))
return;

BOOL IsHung;

if (osver.dwPlatformId&VER;_PLATFORM_WIN32_NT)
IsHung = IsHungAppWindow(hWnd);
else
IsHung = IsHungThread(GetWindowThreadProcessId(hWnd,NULL));

if (IsHung)
printf("Not Responding\n");
else
printf("Running\n");
}

利用未公布API获取CPU使用率

发表于 2004-11-08 | 分类于 技术控 | | 阅读次数:
字数统计: 134 字 | 阅读时长 ≈ 1 分钟

利用ntdll.dll中没有公开的API函数: NtQuerySystemInformation

typedef LONG (WINAPI *PROCNTQSI)(UINT,PVOID,ULONG,PULONG); PROCNTQSI NtQuerySystemInformation;

NtQuerySystemInformation = (PROCNTQSI)GetProcAddress(
                                      GetModuleHandle("ntdll"),
                                     "NtQuerySystemInformation"
                                     );
if (!NtQuerySystemInformation)

{ return; }

// get number of processors in the system
status = NtQuerySystemInformation(SystemBasicInformation,
                          &SysBaseInfo;,sizeof(SysBaseInfo),NULL);
if (status != NO_ERROR)

{ return; } status = NtQuerySystemInformation(SystemTimeInformation, &SysTimeInfo;,sizeof(SysTimeInfo),0); if (status!=NO_ERROR) { return; } // get new CPU’’s idle time status = NtQuerySystemInformation(SystemPerformanceInformation, &SysPerfInfo;,sizeof(SysPerfInfo),NULL); if (status != NO_ERROR) { return; } // if it’’s a first call - skip it if (m_liOldIdleTime.QuadPart != 0) { // CurrentValue = NewValue - OldValue dbIdleTime = Li2Double(SysPerfInfo.liIdleTime) - Li2Double(m_liOldIdleTime); dbSystemTime = Li2Double(SysTimeInfo.liKeSystemTime) - Li2Double(m_liOldSystemTime);

     // CurrentCpuIdle = IdleTime / SystemTime
     dbIdleTime = dbIdleTime / dbSystemTime;

     // CurrentCpuUsage% = 100 - (CurrentCpuIdle * 100) / NumberOfProcessors
     dbIdleTime = 100.0 - dbIdleTime * 100.0 / (double)SysBaseInfo.bKeNumberProcessors + 0.5;

     m_fNewUsges = (UINT)dbIdleTime;
}

VC中的自定义消息

发表于 2004-10-29 | 分类于 技术控 | | 阅读次数:
字数统计: 507 字 | 阅读时长 ≈ 1 分钟

Windows 应用程序所要做的每项工作几乎都是基于消息处理的, Windows 系统消息分为常用 Windows 消息,控件通知消息和命令。然而,有时我们需要定义自己的消息来通知程序什么事情发生了,这就是用户自定义消息。 ClassWizard 并没有提供增加用户自定义消息的功能,所以要使用用户自定义消息,必须手工编写代码。然后 ClassWizard 才可以象处理其它消息一样处理你自定义的消息。具体做法如下详解:

   第一步:定义消息。一个消息实际上是开发 Windows95 应用程序时, Microsoft 推荐用户自定义消息至少是 WM_USER+100 ,因为很多新控件也要使用 WM_USER 消息。

   第二步:实现消息处理函数。该函数使用 WPRAM 和 LPARAM 参数并返回 LPESULT 。

   LPESULT CMainFrame::OnMyMessage(WPARAM wParam, LPARAM lParam){// TODO: 处理用户自定义消息 AfxMessageBox(“ 处理用户自定义消息 “); return 0;}

   第三步:在类头文件的 AFX_MSG 块中说明消息处理函数:    class CMainFrame:public CMDIFrameWnd{

   …

   // 一般消息映射函数

   protected:

   afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

   afx_msg void OnTimer(UINT nIDEvent);

   afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);

   DECLARE_MESSAGE_MAP()}

   第四步:在用户类的消息块中,使用 ON_MESSAGE 宏指令将消息映射到消息处理函数中。    BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)

   ON_WM_CREATE()

   ON_WM_TIMER()

   ON_MESSAGE(WM_MY_MESSAGE, OnMyMessage)

   这样,一个用户自定义消息就可以使用了,如果用户需要一个整个系统唯一的消息,可以调用 SDK 函数 RegisterWindowMessage 并使用 ON_REGISTER_MESSAGE 宏指令取代 ON_MESSAGE 宏指令,其余步骤同上。

   VC++ 为程序员提供了一套功能强大、方便快捷的编程工具,它可以帮你方便的生成窗口、菜单等用户界面,可惜就是做出来的东西都一样,没有一点个性。下面,就介绍一些方法,让我们可以按照自己的设计定制出更加符合自己程序风格的窗口。

用.DEF文件导出DLL中的函数

发表于 2004-10-27 | 分类于 技术控 | | 阅读次数:
字数统计: 854 字 | 阅读时长 ≈ 3 分钟

通常我们在调用DLL时所需的DLL文件必须位于以下三个目录之一:   (1)Windows的系统目录:\windows\system;   (2)DOS中path所指出的任何目录;   (3)程序所在的目录。   一、动态链接库的结构

  动态链接库中定义有两种函数:导出函数(export function)和内部函数(internal function), 导出函数可以被其它模块调用,内部函数只能在库内部使用。我们在用C++定制动态库文件时, 需要编写的就是包含导出函数表的模块定义文件(.DEF)和实现导出函数功能的C++文件。下面以 Sample.dll为例介绍DEF文件和实现文件的结构。   1.模块定义文件(.DEF)是一个或多个用于描述DLL属性的模块语句组成的文本文件,每个DEF文 件至少必须包含以下模块定义语句:   ·第一个语句必须是LIBRARY语句,指出DLL的名字;   ·EXPORTS语句列出被导出函数的名字;   ·可以使用DESCRIPTION语句描述DLL的用途(此句可选);   ·”;”对一行进行注释(可选)。   2.实现文件   实现入口表函数的cpp文件中,包含DLL入口点处理的API函数和导出函数的代码。   二、创建Sample.dll    1.首先创建Sample.dll的工程,启动VC++5.0按以下步骤生成DLL工程:   ·在选单中选择File\New\Project;   ·在工程列表中选择Win32 Dynamic-Link Library;   ·在Project Name中输入工程名:Sample;   ·单击Location右边按钮,选择c:\sample目录;   ·单击OK完成,至此已创建了Sample.dll的工程文件。   2.创建Sample.def文件:   ·在选单中选择File\New\Text File;   ·输入以下代码后保存文件名”Sample.def”:    ;Sample.def    ;指出DLL的名字Sample,链接器将这个名字放到DLL导入库中    LIBRARY Sample    ;定义导出函数ShowMe()为例

   EXPORTS    ShowMe    ;def文件结束   3.创建Sample.cpp    .在选单中选择File\New\C++ Source File项    .输入以下代码后保存文件名”Sample.cpp”    //Sample.cpp    #include 〈windows.h〉    int ShowMe(void);    //DllEntryPoint为DLL入口点函数,负责初试化并终止DLL    BOOL WINAPI DllEntryPoint(HINSTANCE hDLL,DWORD dwReason,LPVOID Reserved)    { switch(dwReason)    { case DLL-PROCESS-ATTACH:    { break; }    case DLL-PROCESS-DETACH:    { break; } }    return TRUE; }    int ShowMe(void)    { //蜂鸣器响一下    MessageBeep((WORD)-1);    MessageBox(“你好!”);    return 1; }   4.编译DLL文件   从Build选单中选择Build Sample.DLL,产生Sample.DLL文件,以后就可以随时调用了。   三、在应用程序中调用DLL文件   在应用程序中要首先装入DLL后才能调用导出表中的函数,例如用MFC创建基于对话框的工 程Test,并在对话框上放置”Load”按钮,你就必须添加装载代码。   1.首先在TestDlg.cpp的首部添加变量设置代码:   //设置全局变量gLibSample用于存储DLL句柄   HINSTANCE gLibSample=NULL;   //第二个变量ShowMe是指向DLL库中ShowMe()函数的指针   typedef int( SHOWME)(void);

  SHOWME ShowMe;   2.利用ClassWizard为”Load”按钮添加装载DLL的代码:   Void CTestDlg::OnLoadButton()   { //要添加的代码如下    if(gLibMyDLL!=NULL)    { MessageBox(“The Sample.DLL has already been load.”);    return; }    //装载Sample.dll,未加路径,将在三个默认路径中寻找    gLibSample=LoadLibrary(“SAMPLE.DLL”);    //返回DLL中ShowMe()函数的地址    ShowMe=(SHOWME)GetProcAddress(gLibSample,”ShowMe”); }   3.只要DLL装载成功,在应用程序中就可以直接调用ShowMe()函数(本程序在Windows 95,VC++5.0中运行通过)。

实时时间显示

发表于 2004-10-26 | 分类于 技术控 | | 阅读次数:
字数统计: 73 字 | 阅读时长 ≈ 1 分钟

用计时器实现: SetTimer(1, 1000, NULL); 然后在响应函数: void CAlertDlg::OnTimer(UINT nIDEvent) { static CString strTemp; COleDateTime dtTime;

// 刷新显示的时间 dtTime = COleDateTime::GetCurrentTime(); strTemp.Format(“现在时间 %02i:%02i:%02i “, dtTime.GetHour(), dtTime.GetMinute(), dtTime.GetSecond()); GetDlgItem(IDC_CURTIME)->SetWindowText(strTemp); //IDC_CURTIME即为窗口显示时间的一个 //CEDIT类控件

}

VC中实现历史记录的全面清除

发表于 2004-10-26 | 分类于 技术控 | | 阅读次数:
字数统计: 9 字 | 阅读时长 ≈ 1 分钟

http://www.vckbase.com/document/viewdoc.asp?id=280

从文件装载图象

发表于 2004-10-26 | 分类于 技术控 | | 阅读次数:
字数统计: 55 字 | 阅读时长 ≈ 1 分钟

  • 这是从文件里装放位图 **/ BOOL CXxxView::OnDraw(CDC* pDC) { HBITMAP bitmap,OldBitmap; bitmap = (HBITMAP)LoadImage(NULL,”xxx.bmp”,IMAGE_BITMAP,
    0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
    
    CDC MemDC; MemDC.CreateCompatibleDC(pDC); OldBitmap=(HBITMAP)MemDC.SelectObject(bitmap); pDC->BitBlt(0,0,400,300,&MemDC;,0,0,SRCCOPY); MemDC.SelectObject(OldBitmap); return TRUE; }

链接错误浅谈

发表于 2004-10-26 | 分类于 技术控 | | 阅读次数:
字数统计: 1.2k 字 | 阅读时长 ≈ 4 分钟

学习VC++时经常会遇到链接错误LNK2001,该错误非常讨厌,因为对于 编程者来说,最好改的错误莫过于编译错误,而一般说来发生连接错误时, 编译都已通过。产生连接错误的原因非常多,尤其LNK2001错误,常常使人不 明其所以然。如果不深入地学习和理解VC++,要想改正连接错误LNK2001非 常困难。   初学者在学习VC++的过程中,遇到的LNK2001错误的错误消息主要为:   unresolved external symbol “symbol”(不确定的外部“符号”)。   如果连接程序不能在所有的库和目标文件内找到所引用的函数、变量或 标签,将产生此错误消息。一般来说,发生错误的原因有两个:一是所引用 的函数、变量不存在、拼写不正确或者使用错误;其次可能使用了不同版本 的连接库。   以下是可能产生LNK2001错误的原因:   一.由于编码错误导致的LNK2001。   1.不相匹配的程序代码或模块定义(.DEF)文件能导致LNK2001。例如, 如果在C++ 源文件内声明了一变量“var1”,却试图在另一文件内以变量 “VAR1”访问该变量,将发生该错误。   2.如果使用的内联函数是在.CPP文件内定义的,而不是在头文件内定 义将导致LNK2001错误。   3.调用函数时如果所用的参数类型同函数声明时的类型不符将会产生 LNK2001。   4.试图从基类的构造函数或析构函数中调用虚拟函数时将会导致LNK2001。   5.要注意函数和变量的可公用性,只有全局变量、函数是可公用的。   静态函数和静态变量具有相同的使用范围限制。当试图从文件外部访问 任何没有在该文件内声明的静态变量时将导致编译错误或LNK2001。   函数内声明的变量(局部变量) 只能在该函数的范围内使用。   C++ 的全局常量只有静态连接性能。这不同于C,如果试图在C++的 多个文件内使用全局变量也会产生LNK2001错误。一种解决的方法是需要时在 头文件中加入该常量的初始化代码,并在.CPP文件中包含该头文件;另一种 方法是使用时给该变量赋以常数。   二.由于编译和链接的设置而造成的LNK2001   1.如果编译时使用的是/NOD(/NODEFAULTLIB)选项,程序所需要的运行 库和MFC库在连接时由编译器写入目标文件模块, 但除非在文件中明确包含 这些库名,否则这些库不会被链接进工程文件。在这种情况下使用/NOD将导 致错误LNK2001。   2.如果没有为wWinMainCRTStartup设定程序入口,在使用Unicode和MFC 时将得到“unresolved external on _WinMain@16”的LNK2001错误信息。   3.使用/MD选项编译时,既然所有的运行库都被保留在动态链接库之内, 源文件中对“func”的引用,在目标文件里即对“impfunc” 的引用。 如果试图使用静态库LIBC.LIB或LIBCMT.LIB进行连接,将在impfunc上发 生LNK2001;如果不使用/MD选项编译,在使用MSVCxx.LIB连接时也会发生LNK2001。   4.使用/ML选项编译时,如用LIBCMT.LIB链接会在_errno上发生LNK2001。   5.当编译调试版的应用程序时,如果采用发行版模态库进行连接也会产 生LNK2001;同样,使用调试版模态库连接发行版应用程序时也会产生相同的 问题。   6.不同版本的库和编译器的混合使用也能产生问题,因为新版的库里可 能包含早先的版本没有的符号和说明。   7.在不同的模块使用内联和非内联的编译选项能够导致LNK2001。如果 创建C++库时打开了函数内联(/Ob1或/Ob2),但是在描述该函数的相应头 文件里却关闭了函数内联(没有inline关键字),这时将得到该错误信息。 为避免该问题的发生,应该在相应的头文件中用inline关键字标志内联函数。   8.不正确的/SUBSYSTEM或/ENTRY设置也能导致LNK2001。   其实,产生LNK2001的原因还有很多,以上的原因只是一部分而已,对初 学者来说这些就够理解一阵子了。但是,分析错误原因的目的是为了避免错 误的发生。LNK2001错误虽然比较困难,但是只要注意到了上述问题,还是能 够避免和予以解决的。

1…44454647
Timothy

Timothy

Timothy的技术博客,记录技术以及生活点滴

564 日志
8 分类
1187 标签
RSS
github twitter
Links
  • ZWWoOoOo
  • 花開未央
  • 守望轩
  • 大漠说程序
  • ChengBo
  • BlueAndHack
  • 程序员小辉
  • 子痕的博客
  • WoodenRobot
  • VPS大佬
  • 毕扬博客
  • VPSDad
  • 猫爪导航
  • ss1271的奋斗
  • Kian.Li
  • YoungForest
  • Fred's Blog
  • Jacklandrin
© 2025 Timothy
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4