Introduction
This article describes the implementation of a remote Windows Mobile through wirleless or wire. by taking snapeshot screen from mobile and save it as compressed jpeg file ,then send it by socket. A desktop application is provided to display the file's image which sent it over socket port .
Background
Capturing mobile screen or desktop screen is the main idea for all remote application sold in market, the idea it's too easy just capture the screen and send it to socket to sent it to desktop application. We can send it as-is (as a BMP but I am always careful about network trafic so I compess it before sending. You can also build a client application to run on the desktop based on this Article instead of from a Mobile Client to remote to your PC while you in work /University /trip etc.
You Will Benefit from this Article:
- You’re interested in Windows mobile development.
- You would like to see how to use socket technology on mobile and desktop.
- learn how to compress file by Zlib library.
- learn how to use wingdi API.
Using the code
- Client Side (mobile application)
- Server Side (Desktop application)
wVersionRequested = MAKEWORD(2,0);
Status = WSAStartup (wVersionRequested, &wsaData);
if (Status != 0) {
ShowErr (TEXT("WSAStartup call failed!!, Error %d\r\n"), WSAGetLastError());
return;
}
1. Initialize the winsock2 Library with specific version you can check version Number From Microsoft
Application version
|
DLL version
|
wVersion requested
|
wVersion
|
wHigh version
|
Result
|
1.1
|
1.1
|
1.1
|
1.1
|
1.1
|
use 1.1
|
1.0 1.1
|
1.0
|
1.1
|
1.0
|
1.0
|
use 1.0
|
1.0
|
1.0 1.1
|
1.0
|
1.0
|
1.1
|
use 1.0
|
1.1
|
1.0 1.1
|
1.1
|
1.1
|
1.1
|
use 1.1
|
1.1
|
1.0
|
1.1
|
1.0
|
1.0
|
Application
fails
|
1.0 1.1
|
1.0 1.1
|
1.1
|
1.1
|
1.1
|
use 1.1
|
1.1 2.2
|
1.1
|
2.2
|
1.1
|
1.1
|
use 1.1 |
Sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if ( Sock == INVALID_SOCKET )
{
MessageBox(TEXT("Error: failed to create socket\n"),MB_OK);
fflush(0);
return ;
}
2. This function creates a socket that is bound to a specific service provider, if you want to connect through TCP Protocol or UDP etc...
m_ServerSockAddr.sin_addr.s_addr=dwIPAddress;
m_ServerSockAddr.sin_family=AF_INET;
m_ServerSockAddr.sin_port=htons(987);
3. Prepare Server Socket : I mean detect which IP and Port Number then you can call the connect function to try connect on this Server.
if ( connect( Sock, (SOCKADDR*) &m_ServerSockAddr, sizeof(m_ServerSockAddr) ) == SOCKET_ERROR)
{
}
4-After Create success Connection with this Server We want to take tour in GDI function to know how how we can take Capture Screen. look for below
HDC hdcScreen = CreateDC(L"DISPLAY", NULL, NULL, NULL);
HDC hdcCapture = CreateCompatibleDC(hdcScreen);
int nWidth = GetDeviceCaps(hdcScreen, HORZRES),
nHeight = GetDeviceCaps(hdcScreen, VERTRES),
nBPP = GetDeviceCaps(hdcScreen, BITSPIXEL);
LPBYTE lpCapture;
BITMAPINFO bmiCapture = { {
sizeof(BITMAPINFOHEADER), nWidth, -(nHeight), 1, 24, BI_RGB, 0, 0, 0, 0, 0,
} };
HBITMAP hbmCapture = CreateDIBSection(hdcScreen, &bmiCapture,
DIB_RGB_COLORS, (LPVOID *)&lpCapture, NULL, 0);
int nCapture = SaveDC(hdcCapture);
SelectObject(hdcCapture, hbmCapture);
StretchBlt(hdcCapture, 0, 0, (nWidth), (nHeight),hdcScreen, 0, 0,nWidth, nHeight, SRCCOPY);
RestoreDC(hdcCapture, nCapture);
DeleteDC(hdcCapture);
DeleteDC(hdcScreen);
int nResult = SaveFileJPEG(lpszFilename, nQuality, (JSAMPLE *)lpCapture, nWidth, nHeight);
DeleteObject(hbmCapture);
Now as I told you we want to compress this Capture and put it inside jpeg file with low size I want to put compress code here but it you want to learn how compress physically consult with Zlib Library
SaveFileJPEG(char *filename, int quality, JSAMPLE *buffer, int width, int height)
{
struct jpeg_compress_struct jcompress;
struct jpeg_error_mgr jerror;
JSAMPROW scanline[1];
FILE *outfile;
memset(&jcompress, 0, sizeof(jcompress));
memset(&jerror, 0, sizeof(jerror));
jcompress.err = jpeg_std_error(&jerror);
jpeg_create_compress(&jcompress);
outfile = fopen(filename, "wb");
if(!outfile) return 1;
jpeg_stdio_dest(&jcompress, outfile);
jcompress.image_width = width;
jcompress.image_height = height;
jcompress.input_components = 3;
jcompress.in_color_space = JCS_RGB;
jpeg_set_defaults(&jcompress);
jpeg_set_quality(&jcompress, quality, TRUE);
jpeg_start_compress(&jcompress, TRUE);
int nStride = width * 3;
int nSize = nStride * height;
for(int i = 2; i < nSize; i += 3){
unsigned char nTemp = buffer[i - 2];
buffer[i - 2] = buffer[i];
buffer[i] = nTemp;
}
while(jcompress.next_scanline < height){
scanline[0] = buffer;
jpeg_write_scanlines(&jcompress, scanline, 1);
buffer += nStride;
}
jpeg_finish_compress(&jcompress);
jpeg_destroy_compress(&jcompress);
fclose(outfile);
return 0;
}
5- Now you are free to send file though socket inside our code you will found Thread Function to do that i saved the capture as jpg File inside windows Directory made some code to check if no change on screen so no need to send file again
pThis->GetScreeny("\\Windows\\1.jpeg", 20);
CFile bmpFile(L"\\Windows\\1.jpeg", CFile::typeBinary | CFile::modeRead);
char *bmpBuf;
unsigned int fileLen = bmpFile.GetLength();
if (fileLen!=oldFileSize)
{
oldFileSize=fileLen;
bmpBuf = new char[fileLen];
bmpFile.Read(bmpBuf,fileLen);
DWORD nBytestoSend=sizeof(MESSAGEHEAD);
m_msgHead.nImageFileSize=fileLen;
send(Sock, (char*)&m_msgHead, nBytestoSend, 0);
int nSend=send(Sock, bmpBuf, fileLen, 0);
}
Before we going to Discuss Server Side Code i want to let you now about important thing what is it ? how we can send click from Server to mobile and the mobile will handle it.
I think you have to Create SubClass and catch some of message to do what ever you want
case WM_KEYDOWN:
case WM_KEYUP:
case WM_SYSKEYUP:
case WM_SYSKEYDOWN:
if (recv (Sock, (char *)MouseData, sizeof(USHORT), 0) == sizeof(USHORT)) {
dwFlags = ((WM_KEYUP == Cmd) || (WM_SYSKEYUP == Cmd)) ? KEYEVENTF_KEYUP : 0;
keybd_event ((BYTE)MouseData[0], 0, dwFlags, 0);
}
break;
Server Side :
WORD VersionRequested = MAKEWORD(2,2);
WSADATA wsaData;
WSAStartup(VersionRequested, &wsaData); if ( wsaData.wVersion != VersionRequested )
{
MessageBox(TEXT("Wrong version or WinSock not loaded\n"),MB_OK);
fflush(0);
}
m_Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if ( m_Socket == INVALID_SOCKET )
{
MessageBox(TEXT("Error: failed to create socket\n"),MB_OK);
fflush(0);
return false;
}
m_ServerSockAddr.sin_family = AF_INET;
m_ServerSockAddr.sin_addr.s_addr = htonl( INADDR_ANY );
m_ServerSockAddr.sin_port = htons(987);
BOOL temp;
int len=sizeof(BOOL);
int hr;
if ( bind( m_Socket, (struct sockaddr *)&m_ServerSockAddr, sizeof(m_ServerSockAddr)) != 0 )
{
MessageBox(TEXT("Error: failed to bind\n"),MB_OK);
closesocket( m_Socket );
return false;
}
if ( listen(m_Socket,SOMAXCONN) != 0)
{
MessageBox(TEXT("Error: failed to Listen\n"),MB_OK);
closesocket( m_Socket );
return false;
}
Now take tour inside my code to Create Thread Function to handle some stuff gook luck and I wish to be able how create application to help you in your life.