📄 clientconnection.cpp
字号:
{
m_opts.m_scale_num = nLocalWidth;
m_opts.m_scale_den = m_si.framebufferWidth;
}
m_opts.m_scale_num = (AUTOSCALE_GRANULARITY * m_opts.m_scale_num + m_opts.m_scale_den/2) / m_opts.m_scale_den;
// denuminator should be as small as possible, so that only small rectangles need to
// be repainted when scaling
int g = gcd(m_opts.m_scale_num, AUTOSCALE_GRANULARITY);
m_opts.m_scale_num /= g;
m_opts.m_scale_den = AUTOSCALE_GRANULARITY / g;
}
// stop auto scaling
void ClientConnection::StopAutoScaling()
{
m_opts.FixScaling();
}
void ClientConnection::CenterMainWindow()
{
RECT workrect;
// Find how large the desktop work area is
SystemParametersInfo(SPI_GETWORKAREA, 0, &workrect, 0);
int workwidth = workrect.right - workrect.left;
int workheight = workrect.bottom - workrect.top;
SetWindowPos(m_hwndMain, HWND_NOTOPMOST,
workrect.left + (workwidth-m_winwidth) / 2,
workrect.top + (workheight-m_winheight) / 2,
m_winwidth, m_winheight, SWP_SHOWWINDOW);
SetForegroundWindow(m_hwndMain);
}
// do we need scrollbars?
void ClientConnection::AdjustScrollbars()
{
// Calculate window dimensions
RECT rect;
GetWindowRect(m_hwndMain, &rect);
m_winwidth = rect.right - rect.left;
m_winheight = rect.bottom - rect.top ;
//if (m_opts.m_ShowToolbar)
//{
// GetWindowRect(m_hwndTBwin, &Rtb);
// SetWindowPos(m_hwndTB,HWND_NOTOPMOST,0,-2,m_winwidth, Rtb.bottom-Rtb.top, SWP_FRAMECHANGED);
// UpdateWindow(m_hwndTB);
//}
//else
//{
// Rtb.top=0;Rtb.bottom=0;
//}
// If the current window size would be large enough to hold the
// whole screen without scrollbars, or if we're full-screen,
// we turn them off. Under CE, the scroll bars are unchangeable.
bool hasScrollbars = false;
if (InFullScreenMode() ||
m_winwidth + 1 >= m_fullwinwidth &&
m_winheight + 1>= m_fullwinheight )
{
ShowScrollBar(m_hwndMain, SB_HORZ, FALSE);
ShowScrollBar(m_hwndMain, SB_VERT, FALSE);
}
else
{
hasScrollbars = true;
ShowScrollBar(m_hwndMain, SB_HORZ, TRUE);
ShowScrollBar(m_hwndMain, SB_VERT, TRUE);
}
// Update these for the record
// And consider that in full-screen mode the window
// is actually bigger than the remote screen.
GetClientRect(m_hwndMain, &rect);
m_cliwidth = min((int)(rect.right - rect.left),
(int)(m_si.framebufferWidth * m_opts.m_scale_num / m_opts.m_scale_den));
m_cliheight = min((int)(rect.bottom - rect.top) ,
(int)(m_si.framebufferHeight * m_opts.m_scale_num / m_opts.m_scale_den));
m_hScrollMax = (int)m_si.framebufferWidth * m_opts.m_scale_num / m_opts.m_scale_den;
m_vScrollMax = (int)m_si.framebufferHeight* m_opts.m_scale_num / m_opts.m_scale_den;
int newhpos, newvpos;
newhpos = max(0,
min(m_hScrollPos,
m_hScrollMax - max(m_cliwidth, 0)
)
);
newvpos = max(0,
min(m_vScrollPos,
m_vScrollMax - max(m_cliheight, 0)
)
);
ScrollWindowEx(m_hwnd,
m_hScrollPos - newhpos,
m_vScrollPos - newvpos,
NULL, &rect, NULL, NULL, SW_INVALIDATE);
m_hScrollPos = newhpos;
m_vScrollPos = newvpos;
if(hasScrollbars)
UpdateScrollbars();
}
// Size the window
void ClientConnection::SizeWindow()
{
// Let's find out how big a window would be needed to display the
// whole desktop (assuming no scrollbars).
RECT fullwinrect;
RECT workrect;
int fbWidth, fbHeight;
if (m_opts.m_scaling) // calculate size of client area
{
fbWidth = m_si.framebufferWidth * m_opts.m_scale_num / m_opts.m_scale_den;
fbHeight = m_si.framebufferHeight * m_opts.m_scale_num / m_opts.m_scale_den;
}
else
{
fbWidth = m_si.framebufferWidth;
fbHeight = m_si.framebufferHeight;
}
SetRect(&fullwinrect, 0, 0, fbWidth, fbHeight);
AdjustWindowRectEx(&fullwinrect, // adjust main window
GetWindowLong(m_hwndMain, GWL_STYLE) & ~WS_VSCROLL & ~WS_HSCROLL,
FALSE, GetWindowLong(m_hwndMain, GWL_EXSTYLE));
// Find how large the desktop work area is
SystemParametersInfo(SPI_GETWORKAREA, 0, &workrect, 0);
int workwidth = workrect.right - workrect.left;
int workheight = workrect.bottom - workrect.top;
m_fullwinwidth = fullwinrect.right - fullwinrect.left;
m_fullwinheight = fullwinrect.bottom - fullwinrect.top;
m_winwidth = min(m_fullwinwidth, workwidth);
m_winheight = min(m_fullwinheight, workheight);
RECT rmain;
GetWindowRect(m_hwndMain, &rmain);
if(!m_sizing && (m_opts.m_fAutoScaling ||
(!m_opts.m_fAutoScaling &&
(m_winwidth<workwidth || m_winheight<workheight))))
{
MoveWindow(m_hwndMain, rmain.left, rmain.top, m_winwidth, m_winheight, TRUE);
}
MoveWindow(m_hwnd, 0, 0, fbWidth, fbHeight, FALSE);
RECT cr, tbRect;
GetClientRect(m_hwndMain, &cr);
GetClientRect(m_hwndTBwin, &tbRect);
if (m_opts.m_ShowToolbar) // display toolbar
{
MoveWindow(m_hwndTBwin, (cr.right - cr.left - tbRect.right + tbRect.left)/2,
0,
tbRect.right - tbRect.left,
tbRect.bottom - tbRect.top, TRUE);
}
else
{
MoveWindow(m_hwndTBwin, (cr.right - cr.left - tbRect.right + tbRect.left)/2,
-32,
tbRect.right - tbRect.left,
tbRect.bottom - tbRect.top, TRUE);
}
// Presentation: show toolbar only in fullscreen mode
ShowWindow(m_hwndTBwin, (m_opts.m_ActiveMode != rfbMC_PresentationClient) ||
m_opts.m_FullScreen ? SW_SHOW:SW_HIDE);
if(m_SecureDesktopDialog)
CenterSecureDesktopDialog();
InvalidateRect(m_hwnd, NULL, FALSE);
m_sizing = false;
AdjustScrollbars();
}
// We keep a local copy of the whole screen. This is not strictly necessary
// for VNC, but makes scrolling & deiconifying much smoother.
void ClientConnection::CreateLocalFramebuffer()
{
omni_mutex_lock l(m_bitmapdcMutex);
// We create a bitmap which has the same pixel characteristics as
// the local display, in the hope that blitting will be faster.
TempDC hdc(m_hwnd);
if (m_hBitmap != NULL)
DeleteObject(m_hBitmap);
m_hBitmap = CreateCompatibleBitmap(hdc, m_si.framebufferWidth, m_si.framebufferHeight);
if (m_hBitmap == NULL)
throw WarningException("Error creating local image of screen");
// Select this bitmap into the DC with an appropriate palette
ObjectSelector b(m_hBitmapDC, m_hBitmap);
PaletteSelector p(m_hBitmapDC, m_hPalette);
// Modif RDV@2002 - Cache Encoding
// Modif sf@2002
if (m_opts.m_fEnableCache)
{
if (m_hCacheBitmap != NULL) DeleteObject(m_hCacheBitmap);
m_hCacheBitmap = CreateCompatibleBitmap(m_hBitmapDC, m_si.framebufferWidth, m_si.framebufferHeight);
vnclog.Print(0, VNCLOG(_T("Cache: Cache buffer bitmap creation")));
}
RECT rect;
SetRect(&rect, 0,0, m_si.framebufferWidth, m_si.framebufferHeight);
COLORREF bgcol = RGB(0, 0, 50);
FillSolidRect(&rect, bgcol);
COLORREF oldbgcol = SetBkColor( m_hBitmapDC, bgcol);
COLORREF oldtxtcol = SetTextColor(m_hBitmapDC, RGB(255,255,255));
rect.right = m_si.framebufferWidth / 2;
rect.bottom = m_si.framebufferHeight / 2;
DrawText (m_hBitmapDC, sz_L62, -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER);
SetBkColor( m_hBitmapDC, oldbgcol);
SetTextColor(m_hBitmapDC, oldtxtcol);
InvalidateRect(m_hwnd, NULL, FALSE);
}
void ClientConnection::SetupPixelFormat() {
// Have we requested a reduction to 8-bit?
if (m_opts.m_Use8Bit)
{
switch (m_opts.m_Use8Bit)
{
case rfbPF256Colors:
m_newFormat = vnc8bitFormat;
break;
case rfbPF64Colors:
m_newFormat = vnc8bitFormat_64;
break;
case rfbPF8Colors:
m_newFormat = vnc8bitFormat_8;
break;
case rfbPF8GreyColors:
m_newFormat = vnc8bitFormat_8Grey;
break;
case rfbPF4GreyColors:
m_newFormat = vnc8bitFormat_4Grey;
break;
case rfbPF2GreyColors:
m_newFormat = vnc8bitFormat_2Grey;
break;
}
vnclog.Print(2, VNCLOG(_T("Requesting 8-bit truecolour")));
// We don't support colormaps so we'll ask the server to convert
}
else if (!m_si.format.trueColour)
{
// We'll just request a standard 16-bit truecolor
vnclog.Print(2, VNCLOG(_T("Requesting 16-bit truecolour")));
m_newFormat = vnc16bitFormat;
}
else
{
// Normally we just use the sever's format suggestion
m_newFormat = m_si.format;
m_newFormat.bigEndian = 0; // except always little endian
// It's silly requesting more bits than our current display has, but
// in fact it doesn't usually amount to much on the network.
// Windows doesn't support 8-bit truecolour.
// If our display is palette-based, we want more than 8 bit anyway,
// unless we're going to start doing palette stuff at the server.
// So the main use would be a 24-bit true-colour desktop being viewed
// on a 16-bit true-colour display, and unless you have lots of images
// and hence lots of raw-encoded stuff, the size of the pixel is not
// going to make much difference.
// We therefore don't bother with any restrictions, but here's the
// start of the code if we wanted to do it.
if (false) {
// Get a DC for the root window
TempDC hrootdc(NULL);
int localBitsPerPixel = GetDeviceCaps(hrootdc, BITSPIXEL);
int localRasterCaps = GetDeviceCaps(hrootdc, RASTERCAPS);
vnclog.Print(2, VNCLOG(_T("Memory DC has depth of %d and %s pallete-based.")),
localBitsPerPixel, (localRasterCaps & RC_PALETTE) ? "is" : "is not");
// If we're using truecolor, and the server has more bits than we do
if ( (localBitsPerPixel > m_newFormat.depth) &&
! (localRasterCaps & RC_PALETTE)) {
m_newFormat.depth = localBitsPerPixel;
// create a bitmap compatible with the current display
// call GetDIBits twice to get the colour info.
// set colour masks and shifts
}
}
}
// The endian will be set before sending
// really change the pixel format when the next full framebuffer arrives
m_WaitForFullUpdate = true;
}
void ClientConnection::SetFormatAndEncodings()
{
// Set pixel format to myFormat
rfbSetPixelFormatMsg spf;
spf.type = rfbSetPixelFormat;
if(m_WaitForFullUpdate)
spf.format = m_newFormat;
else
spf.format = m_myFormat;
spf.format.redMax = Swap16IfLE(spf.format.redMax);
spf.format.greenMax = Swap16IfLE(spf.format.greenMax);
spf.format.blueMax = Swap16IfLE(spf.format.blueMax);
WriteExact((char *)&spf, sz_rfbSetPixelFormatMsg, rfbSetPixelFormat);
// The number of bytes required to hold at least one pixel.
m_minPixelBytes = (spf.format.bitsPerPixel + 7) >> 3;
// Set encodings
char buf[sz_rfbSetEncodingsMsg + MAX_ENCODINGS * 4];
rfbSetEncodingsMsg *se = (rfbSetEncodingsMsg *)buf;
CARD32 *encs = (CARD32 *)(&buf[sz_rfbSetEncodingsMsg]);
int len = 0;
se->type = rfbSetEncodings;
se->nEncodings = 0;
bool useCompressLevel = false;
int i = 0;
// Put the preferred encoding first, and change it if the
// preferred encoding is not actually usable.
for (i = LASTENCODING; i >= rfbEncodingRaw; i--)
{
if (m_opts.m_PreferredEncoding == i)
{
encs[se->nEncodings++] = Swap32IfLE(i);
if ( i == rfbEncodingZlib ||
i == rfbEncodingTight ||
i == rfbEncodingZlibHex)
{
useCompressLevel = true;
}
}
}
// Now we go through and put in all the other encodings in order.
// We do rather assume that the most recent encoding is the most
// desirable!
for (i = LASTENCODING; i >= rfbEncodingRaw; i--)
{
if ( (m_opts.m_PreferredEncoding != i) )
{
encs[se->nEncodings++] = Swap32IfLE(i);
if ( i == rfbEncodingZlib ||
i == rfbEncodingTight ||
i == rfbEncodingZlibHex
)
{
useCompressLevel = true;
}
}
}
// Tight - Request desired compression level if applicable
if ( useCompressLevel && m_opts.m_useCompressLevel &&
m_opts.m_compressLevel >= 0 &&
m_opts.m_compressLevel <= 9) {
encs[se->nEncodings++] = Swap32IfLE( rfbEncodingCompressLevel0 +
m_opts.m_compressLevel );
}
// Tight - Request cursor shape updates if enabled by user
if (m_opts.m_requestShapeUpdates) {
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingXCursor);
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRichCursor);
}
// Tight - Request JPEG quality level if JPEG compression was enabled by user
if ( m_opts.m_enableJpegCompression &&
m_opts.m_jpegQualityLevel >= 0 &&
m_opts.m_jpegQualityLevel <= 9) {
encs[se->nEncodings++] = Swap32IfLE( rfbEncodingQualityLevel0 +
m_opts.m_jpegQualityLevel );
}
// Modif rdv@2002
//Tell the server that we support the special Zlibencoding
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingXOREnable);
// Tight - LastRect - SINGLE WINDOW
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingLastRect);
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingNewFBSize);
// Modif sf@2002
if (m_opts.m_fEnableCache)
{
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCacheEnable);
// vnclog.Print(0, VNCLOG(_T("Cache: Enable Cache sent to Server")));
}
// len = sz_rfbSetEncodingsMsg + se->nEncodings * 4;
int nEncodings = se->nEncodings;
se->nEncodings = Swap16IfLE(se->nEncodings);
omni_mutex_lock l(m_writeMutex); // Otherwise WriteExacts might be interrupted by MouseEvent
WriteExact((char *)buf, sz_rfbSetEncodingsMsg, rfbSetEncodings);
for (int x = 0; x < nEncodings; x++)
{
WriteExact((char *)&encs[x], sizeof(CARD32));
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -