📄 clientconnection.cpp
字号:
vnclog.Print(3, _T("Palette-based display - %d entries, %d reserved\n"),
GetDeviceCaps(m_hBitmapDC, SIZEPALETTE), GetDeviceCaps(m_hBitmapDC, NUMRESERVED));
BYTE buf[sizeof(LOGPALETTE)+216*sizeof(PALETTEENTRY)];
LOGPALETTE *plp = (LOGPALETTE *) buf;
int pepos = 0;
for (int r = 5; r >= 0; r--) {
for (int g = 5; g >= 0; g--) {
for (int b = 5; b >= 0; b--) {
plp->palPalEntry[pepos].peRed = r * 255 / 5;
plp->palPalEntry[pepos].peGreen = g * 255 / 5;
plp->palPalEntry[pepos].peBlue = b * 255 / 5;
plp->palPalEntry[pepos].peFlags = NULL;
pepos++;
}
}
}
plp->palVersion = 0x300;
plp->palNumEntries = 216;
m_hPalette = CreatePalette(plp);
}
// Add stuff to System menu
HMENU hsysmenu = GetSystemMenu(m_hwnd1, FALSE);
if (!m_opts.m_restricted) {
bool save_item_flags = (m_serverInitiated) ? MF_GRAYED : 0;
AppendMenu(hsysmenu, MF_SEPARATOR, NULL, NULL);
AppendMenu(hsysmenu, MF_STRING, IDC_OPTIONBUTTON,
_T("Connection &options...\tCtrl-Alt-Shift-O"));
AppendMenu(hsysmenu, MF_STRING, ID_CONN_ABOUT,
_T("Connection &info\tCtrl-Alt-Shift-I"));
AppendMenu(hsysmenu, MF_STRING, ID_REQUEST_REFRESH,
_T("Request screen &refresh\tCtrl-Alt-Shift-R"));
AppendMenu(hsysmenu, MF_SEPARATOR, NULL, NULL);
AppendMenu(hsysmenu, MF_STRING, ID_FULLSCREEN,
_T("&Full screen\tCtrl-Alt-Shift-F"));
AppendMenu(hsysmenu, MF_STRING, ID_TOOLBAR,
_T("Show &toolbar\tCtrl-Alt-Shift-T"));
AppendMenu(hsysmenu, MF_SEPARATOR, NULL, NULL);
AppendMenu(hsysmenu, MF_STRING, ID_CONN_CTLALTDEL,
_T("Send Ctrl-Alt-&Del"));
AppendMenu(hsysmenu, MF_STRING, ID_CONN_CTLESC,
_T("Send Ctrl-Esc"));
AppendMenu(hsysmenu, MF_STRING, ID_CONN_CTLDOWN,
_T("Ctrl key down"));
AppendMenu(hsysmenu, MF_STRING, ID_CONN_ALTDOWN,
_T("Alt key down"));
AppendMenu(hsysmenu, MF_SEPARATOR, NULL, NULL);
AppendMenu(hsysmenu, MF_STRING | MF_GRAYED, IDD_FILETRANSFER,
_T("Transf&er files...\tCtrl-Alt-Shift-E"));
AppendMenu(hsysmenu, MF_SEPARATOR, NULL, NULL);
AppendMenu(hsysmenu, MF_STRING, ID_NEWCONN,
_T("&New connection...\tCtrl-Alt-Shift-N"));
AppendMenu(hsysmenu, save_item_flags, ID_CONN_SAVE_AS,
_T("&Save connection info as...\tCtrl-Alt-Shift-S"));
}
AppendMenu(hsysmenu, MF_SEPARATOR, NULL, NULL);
AppendMenu(hsysmenu, MF_STRING, IDD_APP_ABOUT,
_T("&About TightVNC Viewer..."));
if (m_opts.m_listening) {
AppendMenu(hsysmenu, MF_SEPARATOR, NULL, NULL);
AppendMenu(hsysmenu, MF_STRING, ID_CLOSEDAEMON,
_T("Close &listening daemon"));
}
DrawMenuBar(m_hwnd1);
m_hToolbar = CreateToolbar();
m_hwnd = CreateWindow("ChildClass",
NULL,
WS_CHILD | WS_CLIPSIBLINGS,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT, // x-size
CW_USEDEFAULT, // y-size
m_hwndscroll, // Parent handle
NULL, // Menu handle
m_pApp->m_instance,
NULL);
m_opts.m_hWindow = m_hwnd;
hotkeys.SetWindow(m_hwnd1);
ShowWindow(m_hwnd, SW_HIDE);
SetWindowLong(m_hwnd, GWL_USERDATA, (LONG) this);
SetWindowLong(m_hwnd, GWL_WNDPROC, (LONG)ClientConnection::WndProc);
if(pApp->m_options.m_toolbar) {
CheckMenuItem(GetSystemMenu(m_hwnd1, FALSE),
ID_TOOLBAR, MF_BYCOMMAND|MF_CHECKED);
}
SaveListConnection();
// record which client created this window
#ifndef _WIN32_WCE
// We want to know when the clipboard changes, so
// insert ourselves in the viewer chain. But doing
// this will cause us to be notified immediately of
// the current state.
// We don't want to send that.
m_initialClipboardSeen = false;
m_hwndNextViewer = SetClipboardViewer(m_hwnd);
#endif
}
HWND ClientConnection::CreateToolbar()
{
const int MAX_TOOLBAR_BUTTONS = 20;
TBBUTTON but[MAX_TOOLBAR_BUTTONS];
memset(but, 0, sizeof(but));
int i = 0;
but[i].iBitmap = 0;
but[i].idCommand = IDC_OPTIONBUTTON;
but[i].fsState = TBSTATE_ENABLED;
but[i++].fsStyle = TBSTYLE_BUTTON;
but[i].iBitmap = 1;
but[i].idCommand = ID_CONN_ABOUT;
but[i].fsState = TBSTATE_ENABLED;
but[i++].fsStyle = TBSTYLE_BUTTON;
but[i++].fsStyle = TBSTYLE_SEP;
but[i].iBitmap = 2;
but[i].idCommand = ID_FULLSCREEN;
but[i].fsState = TBSTATE_ENABLED;
but[i++].fsStyle = TBSTYLE_BUTTON;
but[i].iBitmap = 3;
but[i].idCommand = ID_REQUEST_REFRESH;
but[i].fsState = TBSTATE_ENABLED;
but[i++].fsStyle = TBSTYLE_BUTTON;
but[i++].fsStyle = TBSTYLE_SEP;
but[i].iBitmap = 4;
but[i].idCommand = ID_CONN_CTLALTDEL;
but[i].fsState = TBSTATE_ENABLED;
but[i++].fsStyle = TBSTYLE_BUTTON;
but[i].iBitmap = 5;
but[i].idCommand = ID_CONN_CTLESC;
but[i].fsState = TBSTATE_ENABLED;
but[i++].fsStyle = TBSTYLE_BUTTON;
but[i].iBitmap = 6;
but[i].idCommand = ID_CONN_CTLDOWN;
but[i].fsState = TBSTATE_ENABLED;
but[i++].fsStyle = TBSTYLE_CHECK;
but[i].iBitmap = 7;
but[i].idCommand = ID_CONN_ALTDOWN;
but[i].fsState = TBSTATE_ENABLED;
but[i++].fsStyle = TBSTYLE_CHECK;
but[i++].fsStyle = TBSTYLE_SEP;
but[i].iBitmap = 8;
but[i].idCommand = IDD_FILETRANSFER;
but[i].fsState = TBSTATE_INDETERMINATE;
but[i++].fsStyle = TBSTYLE_BUTTON;
but[i++].fsStyle = TBSTYLE_SEP;
but[i].iBitmap = 9;
but[i].idCommand = ID_NEWCONN;
but[i].fsState = TBSTATE_ENABLED;
but[i++].fsStyle = TBSTYLE_BUTTON;
but[i].iBitmap = 10;
but[i].idCommand = ID_CONN_SAVE_AS;
but[i].fsState = TBSTATE_ENABLED;
but[i++].fsStyle = TBSTYLE_BUTTON;
but[i].iBitmap = 11;
but[i].idCommand = ID_DISCONNECT;
but[i].fsState = TBSTATE_ENABLED;
but[i++].fsStyle = TBSTYLE_BUTTON;
int numButtons = i;
assert(numButtons <= MAX_TOOLBAR_BUTTONS);
HWND hwndToolbar = CreateToolbarEx(m_hwnd1,
WS_CHILD | TBSTYLE_TOOLTIPS |
WS_CLIPSIBLINGS | TBSTYLE_FLAT,
ID_TOOLBAR, 12, m_pApp->m_instance,
IDB_BITMAP1, but, numButtons, 0, 0, 0, 0, sizeof(TBBUTTON));
if (hwndToolbar != NULL)
SendMessage(hwndToolbar, TB_SETINDENT, 4, 0);
return hwndToolbar;
}
void ClientConnection::SaveListConnection()
{
if (!m_serverInitiated) {
TCHAR valname[3];
int dwbuflen = 255;
int i, j;
int maxEntries = pApp->m_options.m_historyLimit;
TCHAR list[80];
HKEY m_hRegKey;
TCHAR buf[256];
DWORD dispos;
TCHAR buf1[256];
itoa(maxEntries, list, 10);
RegCreateKeyEx(HKEY_CURRENT_USER,
KEY_VNCVIEWER_HISTORI, 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
NULL, &m_hRegKey, &dispos);
_tcscpy(buf1, m_opts.m_display);
for ( i = 0; i < maxEntries; i++) {
j = i;
itoa(i, valname, 10);
dwbuflen = 255;
if ((RegQueryValueEx( m_hRegKey, (LPTSTR)valname,
NULL, NULL,
(LPBYTE) buf, (LPDWORD) &dwbuflen) != ERROR_SUCCESS) ||
(_tcscmp(buf, m_opts.m_display) == NULL)) {
RegSetValueEx( m_hRegKey, valname,
NULL, REG_SZ,
(CONST BYTE *)buf1, (_tcslen(buf1)+1));
break;
}
RegSetValueEx(m_hRegKey, valname,
NULL, REG_SZ,
(CONST BYTE *)buf1, (_tcslen(buf1)+1));
_tcscpy(buf1, buf);
}
if (j == maxEntries) {
dwbuflen = 255;
_tcscpy(valname, list);
_tcscpy(buf, "");
RegQueryValueEx( m_hRegKey, (LPTSTR)valname,
NULL, NULL,
(LPBYTE)buf, (LPDWORD)&dwbuflen);
m_opts.delkey(buf, KEY_VNCVIEWER_HISTORI);
}
RegCloseKey(m_hRegKey);
m_opts.SaveOpt(m_opts.m_display,
KEY_VNCVIEWER_HISTORI);
}
}
void ClientConnection::EnableFullControlOptions()
{
if (m_opts.m_ViewOnly) {
SwitchOffKey();
EnableAction(IDD_FILETRANSFER, false);
EnableAction(ID_CONN_CTLALTDEL, false);
EnableAction(ID_CONN_CTLDOWN, false);
EnableAction(ID_CONN_ALTDOWN, false);
EnableAction(ID_CONN_CTLESC, false);
} else {
EnableAction(IDD_FILETRANSFER, m_enableFileTransfers);
EnableAction(ID_CONN_CTLALTDEL, true);
EnableAction(ID_CONN_CTLDOWN, true);
EnableAction(ID_CONN_ALTDOWN, true);
EnableAction(ID_CONN_CTLESC, true);
}
}
void ClientConnection::EnableAction(int id, bool enable)
{
if (enable) {
EnableMenuItem(GetSystemMenu(m_hwnd1, FALSE), id,
MF_BYCOMMAND | MF_ENABLED);
SendMessage(m_hToolbar, TB_SETSTATE, (WPARAM)id,
(LPARAM)MAKELONG(TBSTATE_ENABLED, 0));
} else {
EnableMenuItem(GetSystemMenu(m_hwnd1, FALSE), id,
MF_BYCOMMAND | MF_GRAYED);
SendMessage(m_hToolbar, TB_SETSTATE, (WPARAM)id,
(LPARAM)MAKELONG(TBSTATE_INDETERMINATE, 0));
}
}
void ClientConnection::SwitchOffKey()
{
CheckMenuItem(GetSystemMenu(m_hwnd1, FALSE),
ID_CONN_ALTDOWN, MF_BYCOMMAND|MF_UNCHECKED);
CheckMenuItem(GetSystemMenu(m_hwnd1, FALSE),
ID_CONN_CTLDOWN, MF_BYCOMMAND|MF_UNCHECKED);
SendMessage(m_hToolbar, TB_SETSTATE, (WPARAM)ID_CONN_CTLDOWN,
(LPARAM)MAKELONG(TBSTATE_ENABLED, 0));
SendMessage(m_hToolbar, TB_SETSTATE, (WPARAM)ID_CONN_ALTDOWN,
(LPARAM)MAKELONG(TBSTATE_ENABLED, 0));
SendKeyEvent(XK_Alt_L, false);
SendKeyEvent(XK_Control_L, false);
SendKeyEvent(XK_Shift_L, false);
SendKeyEvent(XK_Alt_R, false);
SendKeyEvent(XK_Control_R, false);
SendKeyEvent(XK_Shift_R, false);
}
void ClientConnection::GetConnectDetails()
{
if (m_opts.m_configSpecified) {
LoadConnection(m_opts.m_configFilename, false);
} else {
SessionDialog sessdlg(&m_opts, this);
if (!sessdlg.DoDialog()) {
throw QuietException("User Cancelled");
}
}
// This is a bit of a hack:
// The config file may set various things in the app-level defaults which
// we don't want to be used except for the first connection. So we clear them
// in the app defaults here.
m_pApp->m_options.m_host[0] = '\0';
m_pApp->m_options.m_port = -1;
m_pApp->m_options.m_connectionSpecified = false;
m_pApp->m_options.m_configSpecified = false;
#ifndef _WIN32_WCE
// We want to know when the clipboard changes, so
// insert ourselves in the viewer chain. But doing
// this will cause us to be notified immediately of
// the current state.
// We don't want to send that.
m_initialClipboardSeen = false;
m_hwndNextViewer = SetClipboardViewer(m_hwnd);
#endif
}
void ClientConnection::Connect()
{
struct sockaddr_in thataddr;
int res;
if (m_connDlg != NULL)
m_connDlg->SetStatus("Connection initiated");
m_sock = socket(PF_INET, SOCK_STREAM, 0);
if (m_sock == INVALID_SOCKET) throw WarningException(_T("Error creating socket"));
int one = 1;
// The host may be specified as a dotted address "a.b.c.d"
// Try that first
thataddr.sin_addr.s_addr = inet_addr(m_host);
// If it wasn't one of those, do gethostbyname
if (thataddr.sin_addr.s_addr == INADDR_NONE) {
LPHOSTENT lphost;
lphost = gethostbyname(m_host);
if (lphost == NULL) {
char msg[512];
sprintf(msg, "Failed to get server address (%s).\n"
"Did you type the host name correctly?", m_host);
throw WarningException(msg);
};
thataddr.sin_addr.s_addr = ((LPIN_ADDR) lphost->h_addr)->s_addr;
};
thataddr.sin_family = AF_INET;
thataddr.sin_port = htons(m_port);
res = connect(m_sock, (LPSOCKADDR) &thataddr, sizeof(thataddr));
if (res == SOCKET_ERROR) {
char msg[512];
sprintf(msg, "Failed to connect to server (%.255s)", m_opts.m_display);
throw WarningException(msg);
}
vnclog.Print(0, _T("Connected to %s port %d\n"), m_host, m_port);
if (m_connDlg != NULL)
m_connDlg->SetStatus("Connection established");
}
void ClientConnection::SetSocketOptions() {
// Disable Nagle's algorithm
BOOL nodelayval = TRUE;
if (setsockopt(m_sock, IPPROTO_TCP, TCP_NODELAY, (const char *) &nodelayval, sizeof(BOOL)))
throw WarningException("Error disabling Nagle's algorithm");
}
void ClientConnection::NegotiateProtocolVersion()
{
rfbProtocolVersionMsg pv;
ReadExact(pv, sz_rfbProtocolVersionMsg);
pv[sz_rfbProtocolVersionMsg] = 0;
if (m_connDlg != NULL)
m_connDlg->SetStatus("Server protocol version received");
// XXX This is a hack. Under CE we just return to the server the
// version number it gives us without parsing it.
// Too much hassle replacing sscanf for now. Fix this!
#ifdef UNDER_CE
m_minorVersion = 8;
#else
int majorVersion, minorVersion;
if (sscanf(pv, rfbProtocolVersionFormat, &majorVersion, &minorVersion) != 2) {
throw WarningException(_T("Invalid protocol"));
}
vnclog.Print(0, _T("RFB server supports protocol version 3.%d\n"),
minorVersion);
if (majorVersion == 3 && minorVersion >= 8) {
m_minorVersion = 8;
} else if (majorVersion == 3 && minorVersion == 7) {
m_minorVersion = 7;
} else {
m_minorVersion = 3;
}
m_tightVncProtocol = false;
sprintf(pv, rfbProtocolVersionFormat, 3, m_minorVersion);
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -