# Remote Protocol Client Application

**GuiRemoteRendererSingle**is a remote client implementation that renders everything to**INativeWindow**offering full user interaction features. A typical example would be:
```c++
class RendererChannel : public Object, public virtual IGuiRemoteProtocolChannelReceiver<WString>
{
public:
    RendererChannel(GuiRemoteRendererSingle* renderer, IGuiRemoteProtocolChannel<WString>* channel)
    {
        // connect to the remote core application
    }

    void OnReceive(const TPackage& package) override
    {
        // send the string away
    }

    void RegisterMainWindow(INativeWindow* _window)
    {
        // begin handling messages
        // when a message is received, call channel->Write
        // when it is a fetal error, call renderer->ForceExitByFatelError()
        // they must be called with GetCurrentController()->AsyncService()->InvokeInMainThread
        // renderer and channel are the arguments of the constructor
    }

    void UnregisterMainWindow()
    {
    }

    void WaitForDisconnected()
    {
        // block until the remote core application tells the remote client the work is done
    }
};

RendererChannel* rendererChannel = nullptr;
GuiRemoteRendererSingle* renderer = nullptr;

void GuiMain()
{
    auto mainWindow = GetCurrentController()->WindowService()->CreateNativeWindow(INativeWindow::Normal);
    mainWindow->SetTitle(L"Connecting ...");
    {
        auto size = mainWindow->Convert(Size(320, 240));
        auto screen = GetCurrentController()->ScreenService()->GetScreen((vint)0);
        auto client = screen->GetClientBounds();
        auto x = client.Left() + (client.Width() - size.x) / 2;
        auto y = client.Top() + (client.Height() - size.y) / 2;
        mainWindow->SetBounds({ {x,y},size });
    }
    rendererChannel->RegisterMainWindow(mainWindow);
    renderer->RegisterMainWindow(mainWindow);
    GetCurrentController()->WindowService()->Run(mainWindow);
    renderer->UnregisterMainWindow();
    rendererChannel->UnregisterMainWindow();
}

int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int CmdShow)
{
    auto jsonParser = Ptr(new glr::json::Parser);
    GuiRemoteRendererSingle remoteRenderer;
    GuiRemoteJsonChannelFromProtocol channelReceiver(&remoteRenderer);
    GuiRemoteJsonChannelStringDeserializer channelJsonDeserializer(&channelReceiver, jsonParser);
    RendererChannel clientRendererChannel(&remoteRenderer, &channelJsonDeserializer);

    channelReceiver.BeforeWrite.Add([&](const ChannelPackageInfo& info) { clientRendererChannel.BeforeWrite(info); });
    channelReceiver.BeforeOnReceive.Add([&](const ChannelPackageInfo& info) { clientRendererChannel.BeforeOnReceive(info); });

    rendererChannel = &clientRendererChannel;
    renderer = &remoteRenderer;
    int result = SetupRawWindowsDirect2DRenderer();
    clientRendererChannel.WaitForDisconnected();
    renderer = nullptr;
    rendererChannel = nullptr;

    return result;
}
```


This sample simplifies all the details leaving the sending and receiving of strings to you. Check out[this test project](https://github.com/vczh-libraries/GacUI/tree/master/Test/GacUISrc/RemotingTest_Rendering_Win32)for a complete example.

