//TODO // This event handler deals with Frambebuffer Updates coming from the host. An // EncodedRectangle object is passed via the VncEventArgs (actually an IDesktopUpdater // object so that *only* Draw() can be called here--Decode() is done elsewhere). // The VncClient object handles thread marshalling onto the UI thread. protected void VncUpdate(object sender, VncEventArgs e) { try { e.DesktopUpdater.Draw(desktop); } catch { throw; } // Before Invalidating the control, specify the rectangle that needs to be // re-painted. This speeds OnPaint dramatically, since the rest of the // screen doesn't need to change. Also, adjust the invalidated rectangle // to accomodate scrolling or centering, since the desktop will either be // clipped or centered on the screen. int x, y; //int desktopImageWidth = (int)(desktop.Size.Width * ScaleX); //int desktopImageHeight = (int)(desktop.Size.Height * ScaleY); int desktopImageWidth = ClientSize.Width; int desktopImageHeight = ClientSize.Height; // определим - то что нужно апдейтить вообще попадает в видимую часть Rectangle newUpdateRectangle = e.DesktopUpdater.UpdateRectangle; if (ShownRectangle.IntersectsWith(newUpdateRectangle)) { newUpdateRectangle.Intersect(ShownRectangle); if (newUpdateRectangle.IsEmpty) return; } else { return; } //if (ClientSize.Width > desktopImageWidth) //{ // int dx = (ClientRectangle.Width - desktopImageWidth) / 2; // x = (int)(e.DesktopUpdater.UpdateRectangle.X * ScaleX) + dx; //} //else //{ // x = (int)(e.DesktopUpdater.UpdateRectangle.X * ScaleX) + AutoScrollPosition.X; //} //if (ClientSize.Height > desktopImageHeight) //{ // int dy = (ClientRectangle.Height - desktopImageHeight) / 2; // y = (int)(e.DesktopUpdater.UpdateRectangle.Y * ScaleY) + dy; //} //else //{ // y = (int)(e.DesktopUpdater.UpdateRectangle.Y * ScaleY) + AutoScrollPosition.Y; //} x = (int)((newUpdateRectangle.Left - ShownRectangle.Left) * ScaleX); y = (int)((newUpdateRectangle.Top - ShownRectangle.Top) * ScaleY); int width = (int) (newUpdateRectangle.Width * ScaleX); int height = (int)(newUpdateRectangle.Height * ScaleY); Rectangle adjusted = new Rectangle(x, y, width, height); //Rectangle adjusted = new Rectangle(x, // y, // (int)(e.DesktopUpdater.UpdateRectangle.Width * ScaleX), // (int)(e.DesktopUpdater.UpdateRectangle.Height * ScaleY)); //if (ClientSize.Width > desktop.Size.Width) //{ // int dx = (ClientRectangle.Width - desktop.Width) / 2; // x = e.DesktopUpdater.UpdateRectangle.X + dx; //} //else //{ // x = e.DesktopUpdater.UpdateRectangle.X + AutoScrollPosition.X; //} //if (ClientSize.Height > desktop.Size.Height) //{ // int dy = (ClientRectangle.Height - desktop.Height) / 2; // y = e.DesktopUpdater.UpdateRectangle.Y + dy; //} //else //{ // y = e.DesktopUpdater.UpdateRectangle.Y + AutoScrollPosition.Y; //} //Rectangle adjusted = new Rectangle(x, // y, // e.DesktopUpdater.UpdateRectangle.Width, // e.DesktopUpdater.UpdateRectangle.Height); Invalidate(adjusted, true); //Invalidate(); if (state == RuntimeState.Connected) { vnc.RequestScreenUpdate( fullScreenRefresh); // Make sure the next screen update is incremental fullScreenRefresh = false; } }
/// <summary> /// Worker thread lives here and processes protocol messages infinitely, triggering events or other actions as necessary. /// </summary> private void GetRfbUpdates() { int rectangles; int enc; // Get the initial destkop from the host RequestScreenUpdate(true); while (true) { if (CheckIfThreadDone()) break; try { switch (rfb.ReadServerMessageType()) { case RfbProtocol.FRAMEBUFFER_UPDATE: rectangles = rfb.ReadFramebufferUpdate(); if (CheckIfThreadDone()) { break; } for (int i = 0; i < rectangles; ++i) { // Get the update rectangle's info Rectangle rectangle; EncodedRectangle er; rfb.ReadFramebufferUpdateRectHeader(out rectangle, out enc); // Build a derived EncodedRectangle type and pull-down all the pixel info er = factory.Build(rectangle, enc); er.Decode(); // Let the UI know that an updated rectangle is available, but check // to see if the user closed things down first. if (!CheckIfThreadDone() && VncUpdate != null) { VncEventArgs e = new VncEventArgs(er); // In order to play nicely with WinForms controls, we do a check here to // see if it is necessary to synchronize this event with the UI thread. if (VncUpdate.Target is System.Windows.Forms.Control) { Control target = VncUpdate.Target as Control; if (target != null) { target.Invoke(VncUpdate, new object[] { this, e }); } } else { // Target is not a WinForms control, so do it on this thread... VncUpdate(this, new VncEventArgs(er)); } } } break; case RfbProtocol.BELL: Beep(500, 300); // TODO: are there better values than these? break; case RfbProtocol.SERVER_CUT_TEXT: if (CheckIfThreadDone()) { break; } Clipboard.SetDataObject(rfb.ReadServerCutText().Replace("\n", Environment.NewLine), true); break; case RfbProtocol.SET_COLOUR_MAP_ENTRIES: // TODO: Needs to be implemented fully // rfb.ReadColourMapEntry(); break; } } catch { OnConnectionLost(); } } }