📄 clientconnection.cpp
字号:
void ClientConnection::Createdib()
{
omni_mutex_lock l(m_bitmapdcMutex);
TempDC hdc(m_hwnd);
BitmapInfo bi;
UINT iUsage;
memset(&bi, 0, sizeof(bi));
rfbPixelFormat *format = m_WaitForFullUpdate ? &m_myFormat : &m_newFormat;
iUsage = format->trueColour ? DIB_RGB_COLORS : DIB_PAL_COLORS;
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biBitCount = format->bitsPerPixel;
bi.bmiHeader.biSizeImage = (format->bitsPerPixel / 8) * m_si.framebufferWidth * m_si.framebufferHeight;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biWidth = m_si.framebufferWidth;
bi.bmiHeader.biHeight = -m_si.framebufferHeight;
bi.bmiHeader.biCompression = (format->bitsPerPixel > 8) ? BI_BITFIELDS : BI_RGB;
bi.mask.red = format->redMax << format->redShift;
bi.mask.green = format->greenMax << format->greenShift;
bi.mask.blue = format->blueMax << format->blueShift;
if (m_hmemdc != NULL) {DeleteDC(m_hmemdc);m_hmemdc = NULL;m_DIBbits=NULL;}
if (m_membitmap != NULL) {DeleteObject(m_membitmap);m_membitmap= NULL;}
// m_hmemdc = CreateCompatibleDC(hdc);
m_hmemdc = CreateCompatibleDC(m_hBitmapDC);
m_membitmap = CreateDIBSection(m_hmemdc, (BITMAPINFO*)&bi.bmiHeader, iUsage, &m_DIBbits, NULL, 0);
ObjectSelector bb(m_hmemdc, m_membitmap);
if (format->bitsPerPixel==8 && format->trueColour)
{
struct Colour {
int r, g, b;
};
Colour rgbQ[256];
for (int i=0; i < (1<<(format->depth)); i++) {
rgbQ[i].b = ((((i >> format->blueShift) & format->blueMax) * 65535) + format->blueMax/2) / format->blueMax;
rgbQ[i].g = ((((i >> format->greenShift) & format->greenMax) * 65535) + format->greenMax/2) / format->greenMax;
rgbQ[i].r = ((((i >> format->redShift) & format->redMax) * 65535) + format->redMax/2) / format->redMax;
}
for (int i=0; i<256; i++)
{
bi.color[i].rgbRed = rgbQ[i].r >> 8;
bi.color[i].rgbGreen = rgbQ[i].g >> 8;
bi.color[i].rgbBlue = rgbQ[i].b >> 8;
bi.color[i].rgbReserved = 0;
}
SetDIBColorTable(m_hmemdc, 0, 256, bi.color);
}
}
// Closing down the connection.
// Close the socket, kill the thread.
void ClientConnection::KillThread()
{
m_bKillThread = true;
m_running = false;
if ( (m_sock != INVALID_SOCKET) && (!keepSocket) ){
shutdown(m_sock, SD_BOTH);
closesocket(m_sock);
m_sock = INVALID_SOCKET;
}
if (m_threadStarted)
WaitForSingleObject(KillEvent, 100000);
}
ClientConnection::~ClientConnection()
{
m_pApp->DeregisterConnection(this);
// Now take some time, there might be some messages on the way which still have to be processed
Sleep(1000);
if (m_pNetRectBuf != NULL)
delete [] m_pNetRectBuf;
LowLevelHook::Release();
//the _this pointer in WndProc is about to be destroyed
//if (m_hwnd != NULL)
// SetWindowLong(m_hwnd, GWL_USERDATA,0);
// Modif sf@2002 - FileTransfer
if (m_pFileTransfer)
{
delete(m_pFileTransfer);
m_pFileTransfer = NULL;
}
// Modif sf@2002 - Text Chat
if (m_pTextChat)
{
delete(m_pTextChat);
m_pTextChat = NULL;
}
if (zis)
delete zis;
if (fis)
delete fis;
if (m_pZRLENetRectBuf != NULL)
delete [] m_pZRLENetRectBuf;
if ( (m_sock != INVALID_SOCKET) && (!keepSocket)) {
shutdown(m_sock, SD_BOTH);
closesocket(m_sock);
m_sock = INVALID_SOCKET;
}
if (m_desktopName != NULL) delete [] m_desktopName;
if (m_netbuf) delete [] m_netbuf;
if (m_hCacheBitmapDC != NULL)
DeleteDC(m_hCacheBitmapDC);
if (m_hCacheBitmapDC != NULL)
DeleteObject(m_hCacheBitmapDC);
if (m_hCacheBitmap != NULL)
DeleteObject(m_hCacheBitmap);
if (m_hBitmapDC != NULL)
DeleteDC(m_hBitmapDC);
if (m_hBitmapDC != NULL)
DeleteObject(m_hBitmapDC);
if (m_hBitmap != NULL)
DeleteObject(m_hBitmap);
if (m_hPalette != NULL)
DeleteObject(m_hPalette);
if (m_hTBImageList != NULL) { ImageList_Destroy(m_hTBImageList); m_hTBImageList = NULL; }
if (m_hTBHottrack != NULL) { ImageList_Destroy(m_hTBHottrack); m_hTBHottrack = NULL; }
if (m_hmemdc != NULL) {DeleteDC(m_hmemdc);m_hmemdc = NULL;m_DIBbits=NULL;}
if (m_membitmap != NULL) {DeleteObject(m_membitmap);m_membitmap = NULL;}
if (m_bmpToolbarBackground != NULL) {DeleteObject(m_bmpToolbarBackground); m_bmpToolbarBackground = NULL; }
if (m_bmpToolbarHandle != NULL) {DeleteObject(m_bmpToolbarHandle); m_bmpToolbarHandle = NULL; }
if (m_bmpToolbarHandleClosed != NULL) {DeleteObject(m_bmpToolbarHandleClosed); m_bmpToolbarHandleClosed = NULL; }
if (m_zipbuf!=NULL)
delete [] m_zipbuf;
if (m_filezipbuf!=NULL)
delete [] m_filezipbuf;
if (m_filechunkbuf!=NULL)
delete [] m_filechunkbuf;
if (m_zlibbuf!=NULL)
delete [] m_zlibbuf;
if (m_hwndTBwin!= 0)
DestroyWindow(m_hwndTBwin);
if (rcSource!=NULL)
delete[] rcSource;
if (rcMask!=NULL)
delete[] rcMask;
if(m_tvinfo != NULL)
delete m_tvinfo;
if(m_msimg)
FreeLibrary(m_msimg);
if(!keepSocket) // if not changing direction
{
SessionDialog::ConnectionClosed(); // show SessionDialog
if(connectionLogUser != "")
{
if (m_server->ConnectionLogging())
{
SYSTEMTIME endTime;
GetSystemTime(&endTime);
ConnectionLog::connectionLog.Write(connectionLogUser, connectionLogStartTime, endTime);
}
}
}
CloseHandle(KillEvent);
}
// You can specify a dx & dy outside the limits; the return value will
// tell you whether it actually scrolled.
bool ClientConnection::ScrollScreen(int dx, int dy)
{
dx = max(dx, -m_hScrollPos);
dx = min(dx, m_hScrollMax-(m_cliwidth)-m_hScrollPos);
dy = max(dy, -m_vScrollPos);
dy = min(dy, m_vScrollMax-(m_cliheight)-m_vScrollPos);
if (dx || dy) {
m_hScrollPos += dx;
m_vScrollPos += dy;
RECT clirect;
RECT Rtb;
GetClientRect(m_hwndMain, &clirect);
if (m_opts.m_ShowToolbar)
GetClientRect(m_hwndTBwin, &Rtb);
else
{
Rtb.top=0;
Rtb.bottom=0;
}
clirect.top += Rtb.top;
clirect.bottom += Rtb.bottom;
ScrollWindowEx(m_hwnd, -dx, -dy, NULL, &clirect, NULL, NULL, SW_INVALIDATE);
UpdateScrollbars();
return true;
}
return false;
}
// ProcessPointerEvent handles the delicate case of emulating 3 buttons
// on a two button mouse, then passes events off to SubProcessPointerEvent.
inline void ClientConnection::ProcessPointerEvent(int x, int y, DWORD keyflags, UINT msg)
{
SubProcessPointerEvent(x, y, keyflags);
}
// SubProcessPointerEvent takes windows positions and flags and converts
// them into VNC ones.
inline void ClientConnection::SubProcessPointerEvent(int x, int y, DWORD keyflags)
{
int mask;
if (m_opts.m_SwapMouse) {
mask = ( ((keyflags & MK_LBUTTON) ? rfbButton1Mask : 0) |
((keyflags & MK_MBUTTON) ? rfbButton3Mask : 0) |
((keyflags & MK_RBUTTON) ? rfbButton2Mask : 0) );
} else {
mask = ( ((keyflags & MK_LBUTTON) ? rfbButton1Mask : 0) |
((keyflags & MK_MBUTTON) ? rfbButton2Mask : 0) |
((keyflags & MK_RBUTTON) ? rfbButton3Mask : 0) );
}
if ((short)HIWORD(keyflags) > 0) {
mask |= rfbButton4Mask;
} else if ((short)HIWORD(keyflags) < 0) {
mask |= rfbButton5Mask;
}
try {
int x_scaled =
(x + m_hScrollPos) * m_opts.m_scale_den / m_opts.m_scale_num;
int y_scaled =
(y + m_vScrollPos) * m_opts.m_scale_den / m_opts.m_scale_num;
SendPointerEvent(x_scaled, y_scaled, mask);
if ((short)HIWORD(keyflags) != 0) {
// Immediately send a "button-up" after mouse wheel event.
mask &= !(rfbButton4Mask | rfbButton5Mask);
SendPointerEvent(x_scaled, y_scaled, mask);
}
} catch (Exception &e) {
e.Report();
PostMessage(m_hwndMain, WM_CLOSE_AFTER_EXCEPTION, EXCEPTION_WARNING, 0);
}
}
//
// RealVNC 335 method
//
inline void ClientConnection::ProcessMouseWheel(int delta)
{
int wheelMask = rfbWheelUpMask;
if (delta < 0) {
wheelMask = rfbWheelDownMask;
delta = -delta;
}
while (delta > 0) {
SendPointerEvent(oldPointerX, oldPointerY, oldButtonMask | wheelMask);
SendPointerEvent(oldPointerX, oldPointerY, oldButtonMask & ~wheelMask);
delta -= 120;
}
}
//
// SendPointerEvent.
//
inline void
ClientConnection::SendPointerEvent(int x, int y, int buttonMask)
{
//!!!! cw@2006
if (m_pFileTransfer->m_fFileTransferRunning && ( m_pFileTransfer->m_fVisible || m_pFileTransfer->m_fOldFTProtocole)) return;
//if (m_pTextChat->m_fTextChatRunning && m_pTextChat->m_fVisible) return;
//omni_mutex_lock l(m_UpdateMutex);
rfbPointerEventMsg pe;
oldPointerX = x;
oldPointerY = y;
oldButtonMask = buttonMask;
pe.type = rfbPointerEvent;
pe.buttonMask = buttonMask;
if (x < 0) x = 0;
if (y < 0) y = 0;
// tight cursor handling
SoftCursorMove(x, y);
// Lizard
// mpmd_thread->MouseEvent(x, y, buttonMask);
// // pe.x = Swap16IfLE(x);
// // pe.y = Swap16IfLE(y);
// //WriteExact((char *)&pe, sz_rfbPointerEventMsg, rfbPointerEvent); // sf@2002 - For DSM Plugin
//
//}
//
//// Lizard - stall avoidance
//inline void
//ClientConnection::ExternalSendPointerEvent(int x, int y, int buttonMask)
//{
// rfbPointerEventMsg pe;
// pe.type = rfbPointerEvent;
// pe.buttonMask = buttonMask;
// End Lizard
pe.x = Swap16IfLE(x);
pe.y = Swap16IfLE(y);
WriteExact((char *)&pe, sz_rfbPointerEventMsg, rfbPointerEvent); // sf@2002 - For DSM Plugin
}
//
// ProcessKeyEvent
//
// Normally a single Windows key event will map onto a single RFB
// key message, but this is not always the case. Much of the stuff
// here is to handle AltGr (=Ctrl-Alt) on international keyboards.
// Example cases:
//
// We want Ctrl-F to be sent as:
// Ctrl-Down, F-Down, F-Up, Ctrl-Up.
// because there is no keysym for ctrl-f, and because the ctrl
// will already have been sent by the time we get the F.
//
// On German keyboards, @ is produced using AltGr-Q, which is
// Ctrl-Alt-Q. But @ is a valid keysym in its own right, and when
// a German user types this combination, he doesn't mean Ctrl-@.
// So for this we will send, in total:
//
// Ctrl-Down, Alt-Down,
// (when we get the AltGr pressed)
//
// Alt-Up, Ctrl-Up, @-Down, Ctrl-Down, Alt-Down
// (when we discover that this is @ being pressed)
//
// Alt-Up, Ctrl-Up, @-Up, Ctrl-Down, Alt-Down
// (when we discover that this is @ being released)
//
// Alt-Up, Ctrl-Up
// (when the AltGr is released)
inline void ClientConnection::ProcessKeyEvent(int virtkey, DWORD keyData)
{
bool down = ((keyData & 0x80000000l) == 0);
// if virtkey found in mapping table, send X equivalent
// else
// try to convert directly to ascii
// if result is in range supported by X keysyms,
// raise any modifiers, send it, then restore mods
// else
// calculate what the ascii would be without mods
// send that
#ifdef _DEBUG
#ifdef UNDER_CE
char *keyname="";
#else
char keyname[32];
if (GetKeyNameText( keyData,keyname, 31)) {
// vnclog.Print(4, VNCLOG(_T("Process key: %s (keyData %04x): virtkey %04x ")), keyname, keyData,virtkey);
// if (virtkey==0x00dd)
// vnclog.Print(4, VNCLOG(_T("Process key: %s (keyData %04x): virtkey %04x ")), keyname, keyData,virtkey);
};
#endif
#endif
try {
KeyActionSpec kas = m_keymap.PCtoX(virtkey, keyData);
if (kas.releaseModifiers & KEYMAP_LCONTROL) {
SendKeyEvent(XK_Control_L, false );
vnclog.Print(5, VNCLOG(_T("fake L Ctrl raised")));
}
if (kas.releaseModifiers & KEYMAP_LALT) {
SendKeyEvent(XK_Alt_L, false );
vnclog.Print(5, VNCLOG(_T("fake L Alt raised")));
}
if (kas.releaseModifiers & KEYMAP_RCONTROL) {
SendKeyEvent(XK_Control_R, false );
vnclog.Print(5, VNCLOG(_T("fake R Ctrl raised")));
}
if (kas.releaseModifiers & KEYMAP_RALT) {
SendKeyEvent(XK_Alt_R, false );
vnclog.Print(5, VNCLOG(_T("fake R Alt raised")));
}
for (int i = 0; kas.keycodes[i] != XK_VoidSymbol && i < MaxKeysPerKey; i++) {
SendKeyEvent(kas.keycodes[i], down );
//vnclog.Print(4, VNCLOG(_T("Sent keysym %04x (%s)")),
// kas.keycodes[i], down ? _T("press") : _T("release"));
}
if (kas.releaseModifiers & KEYMAP_RALT) {
SendKeyEvent(XK_Alt_R, true );
vnclog.Print(5, VNCLOG(_T("fake R Alt pressed")));
}
if (kas.releaseModifiers & KEYMAP_RCONTROL) {
SendKeyEvent(XK_Control_R, true );
vnclog.Print(5, VNCLOG(_T("fake R Ctrl pressed")));
}
if (kas.releaseModifiers & KEYMAP_LALT) {
SendKeyEvent(XK_Alt_L, true );
vnclog.Print(5, VNCLOG(_T("fake L Alt pressed")));
}
if (kas.releaseModifiers & KEYMAP_LCONTROL) {
SendKeyEvent(XK_Control_L, true );
vnclog.Print(5, VNCLOG
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -