Rime输入法核心代码分析——WeaselServer文件夹网络化分析(四)

本文详细分析了WeaselServer.cpp代码,这是Weasel网络化输入法的重要组成部分,主要负责服务器配置和服务,实现实时更新文字库。代码中通过SetDPIawareness设置DPI感知,防止服务进程开启输入法,并检查命令行参数以执行不同操作,如创建用户目录、检查更新等。此外,代码还涉及Windows版本检查,确保在适当环境下运行。
摘要由CSDN通过智能技术生成

2021SC@SDUSC

        在之前的文章中,我们对Weasel输入法的总体结构和相关的头文件WeaselIPC.h进行了分析,接下来我们将从WeaselServer.cpp开始,对于代码的其他部分进行具体的分析。

一、WeaselServer.cpp总体介绍:

        Weasel作为一个可以进行网络化使用的输入法,网络化共享模块的使用是使其与其他输入法不同的重要原因,WeaselServer.cpp作为Weasel网络化部分的重要一环,主要配置了远程服务器相关的重要服务,使得输入法可以通过服务器实现对于文字库的文字系统的实时更新,使得当处于不同网络环境下的用户导入全新的文字库时,可以实现所有用户的文字库进行同时更新,接下来将通过代码进行具体功能的分析.

二、代码驱动的功能分析

        总体模块代码如下图所示:

// WeaselServer.cpp : main source file for WeaselServer.exe
//
//	WTL MessageLoop 封装了消息循环. 实现了 getmessage/dispatchmessage....

#include "stdafx.h"
#include "resource.h"
#include "WeaselService.h"
#include <WeaselIPC.h>
#include <WeaselUI.h>
#include <RimeWithWeasel.h>
#include <WeaselUtility.h>
#include <winsparkle.h>
#include <functional>
#include <memory>

CAppModule _Module;

typedef enum PROCESS_DPI_AWARENESS {
	PROCESS_DPI_UNAWARE = 0,
	PROCESS_SYSTEM_DPI_AWARE = 1,
	PROCESS_PER_MONITOR_DPI_AWARE = 2
} PROCESS_DPI_AWARENESS;

typedef enum MONITOR_DPI_TYPE {
	MDT_EFFECTIVE_DPI = 0,
	MDT_ANGULAR_DPI = 1,
	MDT_RAW_DPI = 2,
	MDT_DEFAULT = MDT_EFFECTIVE_DPI
} MONITOR_DPI_TYPE;

int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
{
	InitVersion();

	// Set DPI awareness (Windows 8.1+)
	if (IsWindows8Point1OrGreater())
	{
		using PSPDA = HRESULT (WINAPI *)(PROCESS_DPI_AWARENESS);
		HMODULE shcore_module = ::LoadLibrary(_T("shcore.dll"));
		if (shcore_module != NULL)
		{
			PSPDA SetProcessDpiAwareness = (PSPDA)::GetProcAddress(shcore_module, "SetProcessDpiAwareness");
			SetProcessDpiAwareness(PROCESS_SYSTEM_DPI_AWARE);
			::FreeLibrary(shcore_module);
		}
	}

	// 防止服务进程开启输入法
	ImmDisableIME(-1);

	WCHAR user_name[20] = {0};
	DWORD size = _countof(user_name);
	GetUserName(user_name, &size);
	if (!_wcsicmp(user_name, L"SYSTEM"))
	{
		return 1;
	}

	HRESULT hRes = ::CoInitialize(NULL);
	// If you are running on NT 4.0 or higher you can use the following call instead to 
	// make the EXE free threaded. This means that calls come in on a random RPC thread.
	//HRESULT hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
	ATLASSERT(SUCCEEDED(hRes));

	// this resolves ATL window thunking problem when Microsoft Layer for Unicode (MSLU) is used
	::DefWindowProc(NULL, 0, 0, 0L);

	AtlInitCommonControls(ICC_BAR_CLASSES);	// add flags to support other controls

	hRes = _Module.Init(NULL, hInstance);
	ATLASSERT(SUCCEEDED(hRes));

	if (!wcscmp(L"/userdir", lpstrCmdLine))
	{
		CreateDirectory(WeaselUserDataPath().c_str(), NULL);
		WeaselServerApp::explore(WeaselUserDataPath());
		return 0;
	}
	if (!wcscmp(L"/weaseldir", lpstrCmdLine))
	{
		WeaselServerApp::explore(WeaselServerApp::install_dir());
		return 0;
	}

	// command line option /q stops the running server
	bool quit = !wcscmp(L"/q", lpstrCmdLine) || !wcscmp(L"/quit", lpstrCmdLine);
	// restart if already running
	{
		weasel::Client client;
		if (client.Connect())  // try to connect to running server
		{
			client.ShutdownServer();
		}
		if (quit)
			return 0;
	}

	bool check_updates = !wcscmp(L"/update", lpstrCmdLine);
	if (check_updates)
	{
		WeaselServerApp::check_update();
	}

	CreateDirectory(WeaselUserDataPath().c_str(), NULL);

	int nRet = 0;

	try
	{
		WeaselServerApp app;
		if (IsWindowsVistaOrGreater())
		{
			PRAR RegisterApplicationRestart = (PRAR)::GetProcAddress(::GetModuleHandle(_T("kernel32.dll")), "RegisterApplicationRestart");
			RegisterApplicationRestart(NULL, 0);
		}
		nRet = app.Run();
	}
	catch (...)
	{
		// bad luck...
		nRet = -1;
	}

	_Module.Term();
	::CoUninitialize();

	return nRet;
}

        首先,我们来看代码的起始部分:

typedef enum PROCESS_DPI_AWARENESS {
	PROCESS_DPI_UNAWARE = 0,
	PROCESS_SYSTEM_DPI_AWARE = 1,
	PROCESS_PER_MONITOR_DPI_AWARE = 2
} PROCESS_DPI_AWARENESS;

typedef enum MONITOR_DPI_TYPE {
	MDT_EFFECTIVE_DPI = 0,
	MDT_ANGULAR_DPI = 1,
	MDT_RAW_DPI = 2,
	MDT_DEFAULT = MDT_EFFECTIVE_DPI
} MONITOR_DPI_TYPE;

       

        利用了两个枚举变量来设置server在不同的环境中所应该进行的分辨率DPI模式,PROCESS_DPI_AWARENESS规定了server是否能够获得具体DPI的三种状态,当进程无法取得具体的分辨率时,对应的int数为0,当进程可以从操作系统得到具体的DPI数值时,对应的DPI为1,当进程从之前的监视器获得具体的DPI数值时,所对应的int数值为2.

        第二个枚举变量则设置了监视器所监视的DPI类型,0代表主要检测有效的DPI,1代表检测角DPI,2代表检测行DPI,监视器默认被设置为监视有效DPI.

int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
{
	InitVersion();

	// Set DPI awareness (Windows 8.1+)
	if (IsWindows8Point1OrGreater())
	{
		using PSPDA = HRESULT (WINAPI *)(PROCESS_DPI_AWARENESS);
		HMODULE shcore_module = ::LoadLibrary(_T("shcore.dll"));
		if (shcore_module != NULL)
		{
			PSPDA SetProcessDpiAwareness = (PSPDA)::GetProcAddress(shcore_module, "SetProcessDpiAwareness");
			SetProcessDpiAwareness(PROCESS_SYSTEM_DPI_AWARE);
			::FreeLibrary(shcore_module);
		}
	}

        此段代码根据Windows的版本来确定DPI的监视状态,如果Windows的版本时8.1以及更高的版本,就将DPI的监视模式设置为可见的.

ImmDisableIME(-1);

	WCHAR user_name[20] = {0};
	DWORD size = _countof(user_name);
	GetUserName(user_name, &size);
	if (!_wcsicmp(user_name, L"SYSTEM"))
	{
		return 1;
	}

        接下来利用ImmDisableIME方法确保server文件不会将输入法打开,ImmDisableIME文件是一个定义在imm.h中的布尔类型方法,当其中传入的值为-1时,则关闭了输入法的启动渠道,使输入法无法启动.本段代码还利用了一个变长的user_name数组来存储登录server时传入的用户名,并通过user_name与SYSTEM进行比较,如果相同,则为SYSTEM模式.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值