GacUIソースコードの概要(一)
12002 ワード
GacUIソースコードの概要(一)
本明細書で説明するGacUIソースコードは、https://github.com/vczh-libraries/GacUI.
GacUIでは、`WinMain`の開始後、最初に実行される関数は`SetupWindowsDirect 2 DRenderer`:
D 2 D 1 Factory、DWriteFactory etc.などの多くのfactoryは、`WinDirect 2 DApplicationDirect 2 DObjectProvider`によって取得できますが、これらのリソースは`WinDirect 2 DApplicationDirect 2 DObjectProvider`に格納されていないことに注意してください.次に`WinMainDirect 2 D`に目を向けます.
まず、`CreateWindowsNativeController`を呼び出してControllerを得ました.このControllerはGacUIの核心と言えます.でも焦らないで、まず`SetCurrentController`が何をしたか見てみましょう.
GacUIには、グローバル変数`currentController`があることがわかります.このControllerがどこで神聖なのか見てみましょう.
次のことがわかります.ウィンドウの また、 は、
`WinClass`は`WNDCLASEX`のパッケージですが、ここに注意してください.
`VczhWindow`のウィンドウプロセスが`WndProc`に登録されていることがわかります.
すなわち、メッセージが来ると、先に述べたグローバルストレージのControllerを取得し、本格的なメッセージ処理をControllerに渡す.Controllerでは、最後に`WinForm`にメッセージを転送することがわかります.
`WinForm`はメッセージを受け取るとListenerに転送されます.
メッセージはそのまま転送されました!
そして
`direct 2 Dlistener`については、言うまでもなく、グローバル変数です(JavaerはいわゆるSingletonを使用していないと批判するかもしれません:)
そして、`renderMain()`を呼び出すと、`RenderMainDirect 2 D`がまた`GuiApplicationMain`、`GuiApplicationMain`自体が`GuiApplicationInitialize`を呼び出すようになり、いよいよ走り出す時が来たようです!まず、システムバージョンに基づいてテーマを選択します(現在GacUIはWindows 10と互換性がありません. から
ちなみにGacUIのレンダリングはの古い手口は、 は、 が表示されます.
この
Controllerの
ああ、やっとプログラムが
本明細書で説明するGacUIソースコードは、https://github.com/vczh-libraries/GacUI.
GacUIでは、`WinMain`の開始後、最初に実行される関数は`SetupWindowsDirect 2 DRenderer`:
int SetupWindowsDirect2DRenderer()
{
CoInitializeEx(NULL, COINIT_MULTITHREADED);
HINSTANCE hInstance=(HINSTANCE)GetModuleHandle(NULL);
WinDirect2DApplicationDirect2DObjectProvider objectProvider;
SetWindowsDirect2DObjectProvider(&objectProvider);
return WinMainDirect2D(hInstance, &RendererMainDirect2D);
}
D 2 D 1 Factory、DWriteFactory etc.などの多くのfactoryは、`WinDirect 2 DApplicationDirect 2 DObjectProvider`によって取得できますが、これらのリソースは`WinDirect 2 DApplicationDirect 2 DObjectProvider`に格納されていないことに注意してください.次に`WinMainDirect 2 D`に目を向けます.
int WinMainDirect2D(HINSTANCE hInstance, void(*RendererMain)())
{
EnableCrossKernelCrashing();
// create controller
INativeController* controller=CreateWindowsNativeController(hInstance);
SetCurrentController(controller);
{
// install listener
Direct2DWindowsNativeControllerListener listener;
controller->CallbackService()->InstallListener(&listener);
direct2DListener=&listener;
// main
RendererMain();
// uninstall listener
direct2DListener=0;
controller->CallbackService()->UninstallListener(&listener);
}
// destroy controller
DestroyWindowsNativeController(controller);
return 0;
}
まず、`CreateWindowsNativeController`を呼び出してControllerを得ました.このControllerはGacUIの核心と言えます.でも焦らないで、まず`SetCurrentController`が何をしたか見てみましょう.
INativeController* currentController=0;
INativeController* GetCurrentController()
{
return currentController;
}
void SetCurrentController(INativeController* controller)
{
currentController=controller;
}
GacUIには、グローバル変数`currentController`があることがわかります.このControllerがどこで神聖なのか見てみましょう.
class WindowsController : public Object, public virtual INativeController, public virtual INativeWindowService
{
protected:
WinClass windowClass;
WinClass godClass;
HINSTANCE hInstance;
HWND godWindow;
Dictionary windows;
INativeWindow* mainWindow;
HWND mainWindowHandle;
WindowsCallbackService callbackService;
WindowsResourceService resourceService;
WindowsAsyncService asyncService;
WindowsClipboardService clipboardService;
WindowsImageService imageService;
WindowsScreenService screenService;
WindowsInputService inputService;
WindowsDialogService dialogService;
次のことがわかります.
WinClass
およびGodWindow
のWindowClass
を管理する.Service
のような多くのInputService
を管理し、入力を処理する.ClipBoardService
、クリップボードを処理する.Dictionary
を処理するときに、WndProc
に従って対応するhWnd
を迅速に見つけるために、WinForm
を維持する.`WinClass`は`WNDCLASEX`のパッケージですが、ここに注意してください.
WindowsController(HINSTANCE _hInstance)
:hInstance(_hInstance)
,windowClass(L"VczhWindow", false, false, WndProc, _hInstance)
,godClass(L"GodWindow", false, false, GodProc, _hInstance)
,...
`VczhWindow`のウィンドウプロセスが`WndProc`に登録されていることがわかります.
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
WindowsController* controller=dynamic_cast(GetCurrentController());
if(controller)
{
LRESULT result=0;
if(controller->HandleMessage(hwnd, uMsg, wParam, lParam, result))
{
return result;
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
すなわち、メッセージが来ると、先に述べたグローバルストレージのControllerを取得し、本格的なメッセージ処理をControllerに渡す.Controllerでは、最後に`WinForm`にメッセージを転送することがわかります.
WindowsForm* window=windows.Values().Get(index);
skipDefaultProcedure=window->HandleMessage(hwnd, uMsg, wParam, lParam, result);
`WinForm`はメッセージを受け取るとListenerに転送されます.
case WM_MBUTTONDBLCLK:
{
NativeWindowMouseInfo info=ConvertMouse(wParam, lParam, false, nonClient);
for(vint i=0;iMiddleButtonDoubleClick(info);
}
}
break;
メッセージはそのまま転送されました!
そして
Direct2DWindowsNativeControllerListener
はDirect2D、3D
に必要ないくつかのFactory:class Direct2DWindowsNativeControllerListener : public Object, public INativeControllerListener
{
public:
Dictionary> nativeWindowListeners;
ComPtr d2dFactory;
ComPtr dwrite;
ComPtr d3d11Device;
...
`direct 2 Dlistener`については、言うまでもなく、グローバル変数です(JavaerはいわゆるSingletonを使用していないと批判するかもしれません:)
そして、`renderMain()`を呼び出すと、`RenderMainDirect 2 D`がまた`GuiApplicationMain`、`GuiApplicationMain`自体が`GuiApplicationInitialize`を呼び出すようになり、いよいよ走り出す時が来たようです!
void GuiApplicationInitialize()
{
Ptr<:itheme> theme;
{
WString osVersion=GetCurrentController()->GetOSVersion();
vint index=osVersion.IndexOf(L';');
if (index == -1)
{
theme=new win8::Win8Theme;
}
else
{
WString osMainVersion=osVersion.Sub(0, index);
if(osMainVersion==L"Windows 8" || osMainVersion==L"Windows Server 2012")
{
theme=new win8::Win8Theme;
}
else
{
theme=new win7::Win7Theme;
}
}
}
GetCurrentController()->InputService()->StartTimer();
GuiApplication app;
application=&app;
GetPluginManager()->Load();
GetGlobalTypeManager()->Load();
theme::SetCurrentTheme(theme.Obj());
GuiMain();
theme::SetCurrentTheme(0);
DestroyPluginManager();
DestroyGlobalTypeManager();
ThreadLocalStorage::DisposeStorages();
}
}
}
}
VerifyVersionInfo
はまたマイクロソフトに廃棄されたためです...).Timer
.Timer
はInputService
が担当する:void WindowsInputService::StartTimer()
{
if(!IsTimerEnabled())
{
SetTimer(ownerHandle, 1, 16, NULL);
isTimerEnabled=true;
}
}
void WindowsInputService::StopTimer()
{
if(IsTimerEnabled())
{
KillTimer(ownerHandle, 1);
isTimerEnabled=false;
}
}
Timer
メッセージの処理はCallbackService
が担当します.void WindowsCallbackService::InvokeGlobalTimer()
{
for(vint i=0;iGlobalTimer();
}
}
ちなみにGacUIのレンダリングは
WM_PAINT
ではなく、このTimer
を使用して16 msごとにトリガーされます.GuiApplication
を定義し、全体のapplication
を設定します.GuiMain
を実行する.通常、GuiMain
には、GetApplication()->Run(&window);
この
Run
は非常に率直です.void GuiApplication::Run(GuiWindow* _mainWindow)
{
if(!mainWindow)
{
mainWindow=_mainWindow;
GetCurrentController()->WindowService()->Run(mainWindow->GetNativeWindow());
mainWindow=0;
}
}
Controllerの
Run
が呼び出されます.
void Run(INativeWindow* window)
{
mainWindow=window;
mainWindowHandle=GetWindowsForm(window)->GetWindowHandle();
mainWindow->Show();
MSG message;
while(GetMessage(&message, NULL, 0, 0))
{
TranslateMessage(&message);
DispatchMessage(&message);
asyncService.ExecuteAsyncTasks();
}
}
ああ、やっとプログラムが
Run
になった.