virtdisp.cpp
来自「老外的一个开源项目」· C++ 代码 · 共 1,089 行 · 第 1/3 页
CPP
1,089 行
HDC dc, dcMem;
DWORD dwThreadID;
long inaddr;
HBITMAP hbm, hbmOld;
WORD *pwSrc, *pwDst = NULL;
int i, offset, cWords;
int cSent;
WORD Color, RepeatCount;
struct {
BITMAPINFOHEADER bmih;
RGBQUAD rgq[256];
} bmi;
DWORD dwCRC, dwOldCRC = 0xf1f1;
CERRECTUPDATE RectObj;
CERPALUPDATE PalObj;
PALETTEENTRY PalEntry;
if (DEBUG_FLAG) ShowErr (TEXT("About to do gethostbyname\r\n"));
WideCharToMultiByte(CP_ACP, 0, v_szHostname, -1,
szHostName, sizeof(szHostName), NULL, NULL);
if ((inaddr = inet_addr(szHostName)) == -1L) {
pHost = gethostbyname(szHostName);
if (pHost) {
/*
* If we find a host entry, set up the internet address
*/
inaddr = *(long *)pHost->h_addr;
} else {
ShowErr (TEXT("Can't find '%hs'\r\n"), szHostName);
return -2;
}
}
// Initialize default values
memset ((char *)&SockAddr, 0, sizeof(SockAddr));
SockAddr.sin_family = AF_INET;
SockAddr.sin_port = htons((u_short)dwSockPort);
SockAddr.sin_addr.S_un.S_addr = inaddr;
Sock = socket (AF_INET, SOCK_STREAM, 0);
if (INVALID_SOCKET == Sock) {
ShowErr (TEXT("Can't create socket\r\n"));
return -3;
}
if (DEBUG_FLAG) ShowErr (TEXT("About to connect, RemoteAddr=0x%X\r\n"), SockAddr.sin_addr.S_un.S_addr);
Status = connect (Sock, (SOCKADDR *)&SockAddr, sizeof(SockAddr));
if (SOCKET_ERROR == Status) {
ShowErr (TEXT("Can't connect\r\n"));
return -4;
}
if (DEBUG_FLAG) ShowErr (TEXT("Connected, Remote Addr=%hs\r\n"), inet_ntoa(SockAddr.sin_addr));
if (send (Sock, (char *)&v_Info, sizeof(v_Info), 0) != sizeof(v_Info)) {
DEBUGMSG (1, (TEXT("Error %d from send of Info\r\n"), WSAGetLastError()));
}
// Start the input thread.
v_hInputThread = CreateThread (NULL, 0, DoInput, (LPVOID)Sock, 0, &dwThreadID);
dc = GetDC(NULL);
bmi.bmih.biSize = sizeof(bmi.bmih);
bmi.bmih.biWidth = cXScreen;
bmi.bmih.biHeight = -(int)cYScreen;
bmi.bmih.biPlanes = 1;
bmi.bmih.biBitCount = (BYTE)cScreenDepth;
bmi.bmih.biSizeImage = 0;
bmi.bmih.biXPelsPerMeter = 0;
bmi.bmih.biYPelsPerMeter = 0;
bmi.bmih.biClrUsed = 0;
bmi.bmih.biClrImportant = 0;
switch (cScreenDepth) {
case 16 :
bmi.bmih.biCompression = BI_BITFIELDS;
// Set the bit masks
// Before directly accessing the display memory for 16-bit displays,
// you have to know how the display controller interprets the 16-bit color mask.
// There are two possible flag settings: KfDirect555 and kfDirect565.
// The 555 translates into a color mask XRRRRRGG.GGGBBBBB for Red-Green-Blue in a short variable,
// while 565 translates into RRRRRXGG.GGGBBBBB.
// XRRRRRGG.GGGBBBBB 0x7C00 0x03E0 0x1F
// RRRRRXGG.GGGBBBBB 0xF800 0x03E0 0x1F
// RRRRRGGG.GGXBBBBB 0xF800 0x07C0 0x1F (HP Device)
// 8/15/00 changed mask to 0x07e0 since it made it work on WinME as well as NT
*(DWORD *)(&bmi.rgq[0]) = 0xF800;
*(DWORD *)(&bmi.rgq[1]) = 0x07e0;
*(DWORD *)(&bmi.rgq[2]) = 0x001F;
break;
case 8 :
bmi.bmih.biCompression = BI_RGB;
for (i=0; i < 256; i++) {
GetSystemPaletteEntries (dc, i, 1, &PalEntry);
bmi.rgq[i].rgbRed = PalEntry.peRed;
bmi.rgq[i].rgbGreen = PalEntry.peGreen;
bmi.rgq[i].rgbBlue = PalEntry.peBlue;
bmi.rgq[i].rgbReserved = 0;
}
// We need to send the palette data to the host.
PalObj.dwObjType = CEROBJ_PALETTE;
PalObj.dwSize = sizeof(bmi.rgq);
if (send (Sock, (char *)&PalObj, sizeof(PalObj), 0) != sizeof(PalObj)) {
ShowErr (TEXT("Unable to send PalObj, Error %d\r\n"), WSAGetLastError());
closesocket (Sock);
Sock = INVALID_SOCKET;
return -1;
}
if (send (Sock, (char *)bmi.rgq, sizeof(bmi.rgq), 0) != sizeof(bmi.rgq)) {
ShowErr (TEXT("Unable to send Palette data, Error %d\r\n"), WSAGetLastError());
closesocket (Sock);
Sock = INVALID_SOCKET;
return -1;
}
break;
case 4 :
case 2 :
// Assume gray-scale.
bmi.bmih.biCompression = BI_RGB;
if (2 == cScreenDepth) {
// Hardcode the palette
bmi.rgq[0].rgbBlue = bmi.rgq[0].rgbGreen = bmi.rgq[0].rgbRed = 0x00;
bmi.rgq[0].rgbReserved = 0x00;
bmi.rgq[1].rgbBlue = bmi.rgq[1].rgbGreen = bmi.rgq[1].rgbRed = 0x80;
bmi.rgq[1].rgbReserved = 0x00;
bmi.rgq[2].rgbBlue = bmi.rgq[2].rgbGreen = bmi.rgq[2].rgbRed = 0xC0;
bmi.rgq[2].rgbReserved = 0x00;
bmi.rgq[3].rgbBlue = bmi.rgq[3].rgbGreen = bmi.rgq[3].rgbRed = 0xFF;
bmi.rgq[3].rgbReserved = 0x00;
for (i=4; i<16; i++) {
bmi.rgq[i].rgbBlue = bmi.rgq[i].rgbGreen
= bmi.rgq[i].rgbRed = bmi.rgq[i].rgbReserved = 0x00;
}
} else {
for (i=0; i < 16; i++) {
bmi.rgq[i].rgbBlue = bmi.rgq[i].rgbGreen = bmi.rgq[i].rgbRed =
i ? (BYTE) ((0x10*i)-1) : 0;
bmi.rgq[i].rgbReserved = 0x00;
}
}
// We need to send the palette data to the host.
// We'll send a 4 bit palette since it will get converted to a 4 bit
// bitmap up there
PalObj.dwObjType = CEROBJ_PALETTE;
PalObj.dwSize = 16*sizeof(bmi.rgq[0]);
if (send (Sock, (char *)&PalObj, sizeof(PalObj), 0) != sizeof(PalObj)) {
ShowErr (TEXT("Unable to send PalObj, Error %d\r\n"), WSAGetLastError());
closesocket (Sock);
Sock = INVALID_SOCKET;
return -1;
}
// Only send the first 16 palette entries
if (send (Sock, (char *)bmi.rgq, 16*sizeof(bmi.rgq[0]), 0) != 16*sizeof(bmi.rgq[0])) {
ShowErr (TEXT("Unable to send Palette data, Error %d\r\n"), WSAGetLastError());
closesocket (Sock);
Sock = INVALID_SOCKET;
return -1;
}
break;
default :
ShowErr (TEXT("Unsupported screen depth %d, write more code\r\n"), cScreenDepth);
closesocket (Sock);
Sock = INVALID_SOCKET;
return -1;
}
// Now map the frame buffer and start copying.
RectObj.dwObjType = CEROBJ_RECT;
RectObj.rect.left = 0;
RectObj.rect.top = 0;
RectObj.rect.right = cXScreen;
RectObj.rect.bottom = cYScreen;
hbm = CreateDIBSection (dc, (PBITMAPINFO)&bmi, DIB_RGB_COLORS, (PVOID *)&pwSrc, NULL, 0);
dcMem = CreateCompatibleDC (dc);
hbmOld = (HBITMAP)SelectObject (dcMem, (HGDIOBJ)hbm);
// Worst case is that I need twice the original buffer for the compressed image
pwDst = (WORD *)LocalAlloc (LMEM_FIXED, 2*cXScreen*cYScreen*cScreenDepth/8);
if (NULL == pwDst) {
ShowErr (TEXT("Unable to allocate destination buffer\r\n"));
closesocket (Sock);
Sock = INVALID_SOCKET;
// This will skip the loop and clean up
}
cWords = (int)cXScreen*cYScreen*cScreenDepth/16;
while (INVALID_SOCKET != Sock) {
// Get the scren image
BitBlt (dcMem, 0, 0, cXScreen, cYScreen, dc, 0, 0, SRCCOPY);
// Compress the image, walk a word at a time
offset = 0;
for (i=0; i < cWords; ) {
RepeatCount = 1;
Color = pwSrc[i];
i++;
while ((i < cWords) && (RepeatCount < 0xF000)) {
if (Color != pwSrc[i]) {
break;
}
i++;
RepeatCount++;
}
pwDst[offset++] = RepeatCount;
pwDst[offset++] = Color;
}
dwCRC = ComputeCRC ((PBYTE)pwDst, offset*sizeof(WORD));
if (dwCRC != dwOldCRC) {
// Send the rec info
RectObj.dwSize = offset;
if (send (Sock, (char *)&RectObj, sizeof(RectObj), 0) != sizeof(RectObj)) {
DEBUGMSG (1, (TEXT("Error %d from send of RectInfo\r\n"), WSAGetLastError()));
break;
}
for (i=0; i < (int)(offset*sizeof(WORD)); i += cSent) {
if (INVALID_SOCKET == Sock) {
break;
}
cSent = send (Sock, ((char *)pwDst)+i, offset*sizeof(WORD)-i, 0);
if (cSent == SOCKET_ERROR) {
DEBUGMSG (1, (TEXT("Error %d from send of screen data\r\n"), WSAGetLastError()));
break;
}
}
if (i != (int)(offset*sizeof(WORD))) {
break;
}
dwOldCRC = dwCRC;
if (v_fPaletteChanged && (8 == cScreenDepth)) {
v_fPaletteChanged = FALSE;
for (i=0; i < 256; i++) {
GetSystemPaletteEntries (dc, i, 1, &PalEntry);
bmi.rgq[i].rgbRed = PalEntry.peRed;
bmi.rgq[i].rgbGreen = PalEntry.peGreen;
bmi.rgq[i].rgbBlue = PalEntry.peBlue;
bmi.rgq[i].rgbReserved = 0;
}
// We need to send the palette data to the host.
PalObj.dwObjType = CEROBJ_PALETTE;
PalObj.dwSize = sizeof(bmi.rgq);
if (send (Sock, (char *)&PalObj, sizeof(PalObj), 0) != sizeof(PalObj)) {
// ShowErr (TEXT("Unable to send PalObj, Error %d\r\n"), WSAGetLastError());
break;
}
if (send (Sock, (char *)bmi.rgq, sizeof(bmi.rgq), 0) != sizeof(bmi.rgq)) {
// ShowErr (TEXT("Unable to send Palette data, Error %d\r\n"), WSAGetLastError());
break;
}
}
} else {
dwSkip++;
}
dwTotal++;
Sleep (v_dwRefreshTime);
}
SelectObject (dcMem, (HGDIOBJ)hbmOld);
DeleteObject ((HGDIOBJ)hbm);
DeleteDC (dcMem);
ReleaseDC (NULL, dc);
if (pwDst) {
LocalFree (pwDst);
}
if (INVALID_SOCKET != Sock) {
closesocket (Sock);
Sock = INVALID_SOCKET;
}
if (INVALID_HANDLE_VALUE != v_hInputThread) {
DEBUGMSG (1, (TEXT("DoConnect: Waiting for input thread to exit\r\n")));
WaitForSingleObject (v_hInputThread, INFINITE);
CloseHandle (v_hInputThread);
v_hInputThread = INVALID_HANDLE_VALUE;
}
if (INVALID_HANDLE_VALUE != v_hConnectThread) {
// Hey, that's me. Just close it
CloseHandle (v_hConnectThread);
v_hConnectThread = INVALID_HANDLE_VALUE;
}
// PostMessage (v_hWnd, IDM_CHK_STAT, 0, 0);
PostMessage (v_hWnd, WM_CLOSE, 0, 0);
DEBUGMSG (1, (TEXT("DoConnect thread exiting\r\n")));
return 0;
}
// Following from aygshell.h in Rapier
typedef BOOL (*LPFSHSipPreference)(HWND hwnd, SIPSTATE st);
#define SHFS_SHOWTASKBAR 0x0001
#define SHFS_HIDETASKBAR 0x0002
#define SHFS_SHOWSIPBUTTON 0x0004
#define SHFS_HIDESIPBUTTON 0x0008
#define SHFS_SHOWSTARTICON 0x0010
#define SHFS_HIDESTARTICON 0x0020
typedef BOOL (*LPFSHFullScreen)(HWND hwndRequester, DWORD dwState);
#define SHCMBF_EMPTYBAR 0x0001
#define SHCMBF_HIDDEN 0x0002 // create it hidden
#define SHCMBF_HIDESIPBUTTON 0x0004
typedef struct tagSHMENUBARINFO
{
DWORD cbSize; // IN - Indicates which members of struct are valid
HWND hwndParent; // IN
DWORD dwFlags; // IN - Some features we want
UINT nToolBarId; // IN - Which toolbar are we using
HINSTANCE hInstRes; // IN - Instance that owns the resources
int nBmpId;
int cBmpImages; // IN - Count of bitmap images
HWND hwndMB; // OUT
} SHMENUBARINFO, *PSHMENUBARINFO;
typedef BOOL (*LPFSHCreateMenuBar)(SHMENUBARINFO *pmbi);
LPFSHSipPreference pfSipPref = NULL;
LPFSHFullScreen pfFullScreen = NULL;
LPFSHCreateMenuBar pfCreateMenu = NULL;
void
InitSIPStuff ()
{
HINSTANCE hAYGShell;
if (hAYGShell = LoadLibrary(TEXT("aygshell.dll"))) {
pfSipPref = (LPFSHSipPreference)GetProcAddress (hAYGShell, TEXT("SHSipPreference"));
pfFullScreen = (LPFSHFullScreen)GetProcAddress (hAYGShell, TEXT("SHFullScreen"));
pfCreateMenu = (LPFSHCreateMenuBar)GetProcAddress (hAYGShell, TEXT("SHCreateMenuBar"));
if (pfSipPref && pfFullScreen && pfCreateMenu) {
// Must be a PocketPC app?
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?