Sign in to follow this  
Followers 0
JScript

Remote desktop

14 posts in this topic

Hello guys

I'm testing several ways to send only what has changed on the remote screen to the client computer, I've got a way to just send the window that the mouse is on top, works well and performance is excellent because only the window is sent out instead of the whole screen!

But I saw this link posted by @UEZ
that caught my attention on the possibility of sending only what was changed on the remote computer, below are the tests I did:

When starting, the program sends the entire screen:

t2qewYa.jpg

Below an example of when the mouse is moved, with that I send only what has changed:

e026wXC.jpg

However, you notice that the whole background was deleted, leaving only what has changed on the server!

Here is the $ROP used on the server: BITOR ($ MERGECOPY, $ DSTINVERT)

And the $ROP used in client: $SRCCOPY

If I use the $ROP $SRCAND in the client, the screen goes like this:

K84X7lZ.jpg

If anyone has an idea how to solve this, I would be very grateful!

JS


http://forum.autoitbrasil.com/ (AutoIt v3 Brazil!!!)

Somewhere Out ThereJames Ingram

somewh10.png

dropbo10.pngDownload Dropbox - Simplify your life!
Your virtual HD wherever you go, anywhere!

Share this post


Link to post
Share on other sites



Allow me to pilot from the seat of my pants.

To AND them is to say that for each pixel if one and the other are the same, then the result is true.  So, to superimpose two different images will be not likely that two pixels will be the same.  Am I thinking about this right?

Share this post


Link to post
Share on other sites

To send only the difference might be reduce the amount of data but it is not easy to assemble the diff images to produce a new image in a efficient way.

I you want have a look to DeskStream project on German forum.

Br,

UEZ


Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯

Share this post


Link to post
Share on other sites

Yes, they use this code below which seems to compare two images and sends only the difference, is it?

Func VergleicheBilder()
    $videomode = 0
    _("use32")
    _("mov esi,[esp+4]") ;Pointer des Bildneu in edx neu
    _("mov edi,[esp+8]") ;Pointer des Bildalt in edx  alt
    _("mov ecx,[esp+12]") ;Größe der bilder in ecx
    _("mov ebx,[esp+16]") ;pointer auf infostruct

    _("mov edx,esi") ;offset speichern

    _("mov eax,0xf0fcf0") ;Bitmuster, um die unteren bits abzuschneiden RGB=11111000 11111100 11111000
    _("movd xmm3,eax") ;eax in die untersten 32 bit von xmm3
    _("punpckldq xmm3,xmm3") ;unterstes pixel nach bit32-bit64
    _("punpckldq xmm3,xmm3") ;in allen "pixeln" steht nun die Maske
    _("")

    _("align 16") ;code aligning bringt ca 5-10% geschwindigkeit!

    _("sub edi,16")
    _("sub esi,16")
    _("add ecx,4")

    _("_schleife:")
    _("sub ecx,4") ;anzahl pixel
    _("cmp ecx,11")
    _("jbe _ende") ;wenn bitmapende erreicht, raus

    _("add edi,16") ;nächste 4 pixel
    _("add esi,16") ;nächste 4 pixel
    _("align 16") ;code aligning bringt ca 5-10% geschwindigkeit!
    _("_schleife2:")
    _("movdqu xmm0,[edi]") ;farben 4 pixel alt in xmm0
    _("pand xmm0,xmm3") ;untere bits der farben abschneiden
    _("movdqu xmm1,[esi]") ;farben 4 pixel neu in xmm1
    _("pand xmm1,xmm3") ;untere bits der farben abschneiden
    _("pcmpeqd xmm1,xmm0") ;farben 4 pixel source vergleichen, gleiche pixel ergeben Bit=1
    _("movmskps eax,xmm1") ;4 msb ins eax 0-4
    _("cmp eax,15") ;eax=15 die ersten bits sind 1 ?
    _("je _schleife") ;wenn eax=1111 => 4 pixel gleich, die 4 nächsten


    _("not eax") ;bitwerte umkehren, aus 0 wird 1, ungleiche pixel sind 1
    _("and eax,15") ;nur die ersten 4 bits



;~     If $videomode = 1 Then ;wenn video übertragen wird, einzelne pixel rausfiltern
;~         _("push ebx")      ;ebx retten
;~         _("bsr ebx,eax")   ;von links suchen
;~         _("bsf eax,eax")   ;von rechts suchen aus den 4 msb´s die richtigen adressen machen
;~         _("cmp eax,ebx")   ;wenn nur ein pixel von 4 ungleich, dann nicht ausgeben!
;~         _("pop ebx")
;~         _("je _schleife")
;~     Else                   ;bei textübertragung
    _("bsf eax,eax") ;von rechts suchen aus den 4 msb´s die richtigen adressen machen
;~     EndIf

    _("sub ecx,eax") ;anzahl verbleibender pixel reduzieren
    _("shl eax,2") ;eax=eax*4 ;in eax steht nun das offset zwischen 0 und 12 ab edi/esi für das erste ungleiche pixel
    _("add edi,eax") ;pixel edi
    _("add esi,eax") ;pixel esi

;~     _("")
    _("")
    _("")
    _("")
    _("align 16") ;code aligning bringt ca 5-10% geschwindigkeit!
    ;
    _("mov eax,[esi]") ; Pixelfarbe von bildneu in eax schieben
    _("and eax,0xF8FCF8") ;nur RRGGBB
    _("movd xmm5,eax") ;ursprüngliches pixel speichern
    _("sub esi,edx") ;offset subtrahieren, übrig bleibt die adresse des pixels gezählt von 0
    _("shr esi,2") ;adresse geteilt durch 4, = pixelposition
    _("mov [ebx],esi") ;Adresse des ungleichen pixels in infostruct


    _("push edx") ;sichern
    _("push ebx") ;sichern
    _("mov ebx,[esi*4+edx+4]") ;nächstes pixel aus neuer bitmap holen
    _("and ebx,0xF8FcF8") ;nur RRGGBB
    _("mov edx,[edi+4]") ;nächstes pixel aus alter bitmap holen
    _("and edx,0xF8FcF8") ;nur RRGGBB
    _("cmp edx,eax") ;pixel neu und pixel alt gleich?

;~     _("jmp _keineaufeinanderfolgenden")
    _("je _einzelnespixel") ;einzelnes pixel in infostruct
    ;wenn mehrere aufeinanderfolgende pixel esi sich von edi unterscheiden,
    ;kann man die jeweilige adresse sparen! bit 22 setzen!
    ;[esi+4]<>[edi+4]  beide folgenden pixel unterschiedlich
    _("cmp ebx,eax")
    _("je _aufeinanderfolgendegleiche") ;[esi]=[esi+1]
    _("pop ebx")
    _("pop edx") ;56
    _("")
    _("")
    _("")
    _("")
    _("lea esi,[esi*4+edx]")
    _("push ecx") ;zähler sichern
    _("xor byte[ebx+2],64") ;bit in adresse setzen, dass aufeinanderfolgende farben kommen
    _("xor ecx,ecx") ;ecx=0 zähler ungleiche
    _("_farbeschreiben:")
    _("cmp ecx,3")
    _("je _anzschreiben") ;8bit=maximal 255
    _("add ecx,1")
    _("shr eax,3") ;R an Grenze zu ax schieben
    _("shl ax,3") ;G an die rechte seite von R schieben
    _("shr eax,2") ;RG an Grenze zu al schieben
    _("shl al,2") ;B rechts ans RG schieben
    _("shr eax,3") ;RGB steht nun in 16Bit
    _("mov [ebx+2+2*ecx],ax") ; farbe schreiben
    _("mov eax,[esi+4*ecx]") ;pixel aus neuer bitmap holen
    _("and eax,0xF8FcF8") ;nur RRGGBB
    _("push edx")
    _("mov edx,[edi+4*ecx]") ;pixel aus alter bitmap holen
    _("and edx,0xF8FcF8") ;nur RRGGBB
    _("cmp edx,eax") ;pixelneu und pixelalt gleich?
    _("pop edx")
    _("jne _farbeschreiben") ;nicht gleich, dann farbe schreiben
    _("")
    _("")
    _("_anzschreiben:") ;anzahl der farb-words in ebx+3 schreiben
    _("mov byte[ebx+3],cl") ;anzahl schreiben
    _("lea esi,[esi+ecx*4]") ;adresse angleichen
    _("lea edi,[edi+ecx*4]") ;adresse angleichen
    _("lea ebx,[ebx+4+2*ecx]") ;ebx anpassen
    _("mov eax,ecx") ;
    _("pop ecx")
    _("sub ecx,eax")
    _("cmp ecx,11")
    _("jbe _ende")
    _("jmp _schleife2")
    _("")
    _("")
    _("")
    _("")
    _("_einzelnespixel:")
    _("pop ebx") ;sichern
    _("pop edx") ;sichern
    _("shr eax,3") ;R an Grenze zu ax schieben
    _("shl ax,3") ;G an die rechte seite von R schieben
    _("shr eax,2") ;RG an Grenze zu al schieben
    _("shl al,2") ;B rechts ans RG schieben
    _("shr eax,3") ;RGB steht nun in 16Bit
    _("mov [ebx+3],ax") ;Farbe des ungleichen pixels in infostruct
    _("lea esi,[esi*4+edx+4]") ;adresse wiederherstellen  100
    _("add ebx,5") ;position innerhalb der infostruct
    _("add edi,4") ; ein pixel weiterspringen Zielbitmap
    ;   _("add esi,4")             ; ein pixel weiterspringen Quellbitmap
    _("dec ecx") ;ein pixel weniger zu bearbeiten
    _("cmp ecx,11")
    _("jbe _ende") ;wenn gesamte seite durchsucht ist, dann ende  57
    _("jmp _schleife2")
    _("")



    ;mehrere gleichfarbige pixel hintereinander werden zusammengefasst
    _("_aufeinanderfolgendegleiche:")
    _("pop ebx") ;sichern
    _("pop edx") ;sichern
    _("shr eax,3") ;R an Grenze zu ax schieben
    _("shl ax,3") ;G an die rechte seite von R schieben
    _("shr eax,2") ;RG an Grenze zu al schieben
    _("shl al,2") ;B rechts ans RG schieben
    _("shr eax,3") ;RGB steht nun in 16Bit
    _("mov [ebx+3],ax") ;Farbe des ungleichen pixels in infostruct
    _("lea esi,[esi*4+edx+4]") ;adresse wiederherstellen
    _("add ebx,5") ;position innerhalb der infostruct
    _("add edi,4") ; ein pixel weiterspringen Zielbitmap
    ;    _("add esi,4")            ; ein pixel weiterspringen Quellbitmap
    _("dec ecx")
    _("cmp ecx,65")
    _("jbe _ende") ;wenn gesamte seite durchsucht ist, dann ende  57


    _("push ecx") ;retten
    _("push edx") ;retten
    _("movd eax,xmm5") ;ursprüngliches pixel laden
    _("xor ecx,ecx") ;ecx=0

    _("_gleichespixel:")
    _("mov edx,[esi+ecx*4]") ;edx=nächstes pixel
    _("and edx,0xF8FCF8") ;nur RRGGBB, RR 5 bit, GG 6 bit, BB 5 bit
    _("cmp eax,edx") ;nächstes pixel gleiche farbe?
    _("jne _ausgabegleiche") ;springe, wenn pixel unterschiedlich

    _("add ecx,1") ;pixel sind gleich, also eins mehr
    _("cmp ecx,255") ;255 gleiche pixel?
    _("je _ausgabegleiche") ;8bit-zähler ist voll, also struct schreiben
    _("jmp _gleichespixel") ;nächstes überprüfen 70


    _("_ausgabegleiche:") ;ab hier werden die gleichen pixel in die struct geschrieben
    _("xor eax,eax") ;eax=0
    _("cmp ecx,0") ;keine gleichen pixel vorhanden
    _("je _pop") ;wenn keine gleichen vorhanden sind, pop und weiter

    _("xor byte[ebx-3],128") ;bit in adresse setzen als flag, damit client weiss, dass mehrere pixel gleiche farbe haben
    _("mov byte[ebx],cl") ;anzahl der gleichen pixel schreiben
    _("add ebx,1") ;zähler f. struct eins erhöhen
    _("lea esi,[esi+ecx*4]") ;adresse angleichen
    _("lea edi,[edi+ecx*4]") ;adresse angleichen
    _("mov eax,ecx") ;anzahl gleiche pixel in eax

    _("_pop:")
    _("pop edx")
    _("pop ecx")
    _("sub ecx,eax") ;ecx angleichen
    _("cmp ecx,11")
    _("jbe _ende") ;wenn bitmapende erreicht, raus
    _("jmp _schleife2")
    ;ende, ausgabe der btes in infostruct
    _("_ende:")
    _("emms")
    _("sub ebx,[esp+16]") ;anzahl beschriebener bytes
    _("mov eax,ebx") ;anzahl an autoit zurückgeben
    ;  _("mov eax,3333")                       ;anzahl an autoit zurückgeben

    _("ret") ;
EndFunc   ;==>VergleicheBilder

So in BitBlt not afford to do this, I'm correct?

JS


http://forum.autoitbrasil.com/ (AutoIt v3 Brazil!!!)

Somewhere Out ThereJames Ingram

somewh10.png

dropbo10.pngDownload Dropbox - Simplify your life!
Your virtual HD wherever you go, anywhere!

Share this post


Link to post
Share on other sites

Sorry I cannot say because my ASM knowledge is limited. Regarding BitBlt I don't know either, might be possible but probably too slow.

Br,

UEZ


Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

Ok, I'm analyzing what VNC is to compare the images, see the function:

bool vncDesktop::FastDetectChanges(rfb::Region2D &rgn, rfb::Rect &rect, int nZone, bool fTurbo)
{
    bool returnvalue=false;
    bool fInitGrid = false;
    bool fIncCycle = false;
    // For more accuracy, we could use 24 or even 16
    const int PIXEL_BLOCK_SIZE  = 32; // Pixels Grid definition
    const int GRID_OFFSET = 4;  // Pixels Grid shifting during cycle (in pixels)
                                // The number of grid per zone is PIXEL_BLOCK_SIZE/GRID_OFFSET (must be int !)
    int x, y;
    int xo, yo;
    // WindowsList lWList;
    WindowsList::iterator iWindow;

    // In turbo mode, we clear the list of windows at each iteration -> Lot of updates because 
    //  the same windows can be detected several times during a complete cycle
    // (To avoid this pb, we must update all the grids at the same coordinate when a pixel of 
    // one grid has changed -> later)
    // Otherwise we only clear it each time the Grid cycle loops -> Less updates, less framerate,
    // less CPU, less bandwidth
    if (fTurbo || (m_nGridCycle == 0))
        m_lWList.clear();

    // Create all the Grids (for all the 5 zones (4 quarter screens + 1 full screen)
    // Actually, the quarter screens are not utilized in v1.1.0 but it does not
    // generate any overhead neither additionnal memory consumption (see below)
    if (m_lGridsList.empty())
    {
        for (int i = 0; i < (5 * PIXEL_BLOCK_SIZE / GRID_OFFSET); i++)
        {
            RGBPixelList *pList = new RGBPixelList;
            pList->reserve((rect.height() / PIXEL_BLOCK_SIZE) * (rect.width() / PIXEL_BLOCK_SIZE));
            if (pList != NULL)
            {
                m_lGridsList.push_back(pList);
                vnclog.Print(LL_INTINFO, VNCLOG("### PixelsGrid %d created !\n"), i);
            }
        }
    }

    PixelEngine.PixelCaptureEngineInit(m_hrootdc, m_hmemdc, m_membitmap, m_fCaptureAlphaBlending && !m_Black_window_active, 
                                   m_DIBbits, m_scrinfo.format.bitsPerPixel / 8, m_bytesPerRow);
    // We test one zone at a time 
    // vnclog.Print(LL_INTINFO, VNCLOG("### Polling Grid %d - SubGrid %d\n"), nZone, m_nGridCycle); 
    GridsList::iterator iGrid;
    int nGridPos = (nZone * PIXEL_BLOCK_SIZE / GRID_OFFSET) + m_nGridCycle;
    int nIndex = nGridPos;

    iGrid = m_lGridsList.begin();
    std::advance(iGrid, nGridPos);

    RGBPixelList *pThePixelGrid  =  *iGrid;
    RGBPixelList::iterator iPixelColor =  pThePixelGrid->begin();

    if (nZone == 0 || nZone == 4)
    {
       // vnclog.Print(LL_INTINFO, VNCLOG("### IncCycle Please !\n")); 
       fIncCycle = true;
    }

    if (pThePixelGrid->empty())
    {
        // vnclog.Print(LL_INTINFO, VNCLOG("### PixelsGrid Init\n"));
        fInitGrid = true;
    }

    int nOffset = GRID_OFFSET * m_nGridCycle;
    HWND hDeskWnd = GetDesktopWindow();

    PixelEngine.CaptureRect(rect);
    if (PixelEngine.m_bIsVista) returnvalue=true;
    // Try to detect if screen is almost idle
    // no need to poll static screens very fast, it only use cpu
    change_found=0;
    // We walk our way through the Grids
    for (y = rect.tl.y; y < (rect.br.y -nOffset -1) ; y += PIXEL_BLOCK_SIZE)
    {
        yo = y + nOffset;

        for (x = rect.tl.x; x < (rect.br.x -nOffset); x += PIXEL_BLOCK_SIZE)
        {
            xo = x + nOffset;

            // Read the pixel's color on the screen
            COLORREF PixelColor = PixelEngine.CapturePixel(xo, yo);

            // If init list
            if (fInitGrid)
            {
               pThePixelGrid->push_back(PixelColor);
               // vnclog.Print(LL_INTINFO, VNCLOG("### PixelsGrid Init : Pixel xo=%d - yo=%d - C=%ld\n"), xo, yo, (long)PixelColor); 
               continue;
            }

//          vnclog.Print(LL_INTINFO, VNCLOG("### GetPixel %i\n"),OSversion());
            // If the pixel has changed
            if (*iPixelColor != PixelColor )
            {
                change_found=1;
                // Save the new Pixel in the list
                *iPixelColor = PixelColor;

                // Then find the corresponding Window
                POINT point;
                RECT rect;

                point.x = xo;
                point.y = yo;

                // Find the smallest, non-hidden, non-disabled Window containing this pixel
                // REM: We don't use ChildWindowFromPoint because we don't want of hidden windows
                HWND hwnd = WindowFromPoint(point);

                // Look if we've already detected this window
                if (hwnd != hDeskWnd)
                {
                    // Look if we've already detected this window
                    if (std::find(m_lWList.begin(), m_lWList.end(), hwnd) == m_lWList.end())
                    {               
                        // Add the corresponding rect to the cache region 
                        if (GetWindowRect(hwnd, &rect))
                            {
                                //Buffer coordinates
                                rect.left-=m_ScreenOffsetx;
                                rect.right-=m_ScreenOffsetx;
                                rect.top-=m_ScreenOffsety;
                                rect.bottom-=m_ScreenOffsety;
                                rfb::Rect wrect = rfb::Rect(rect).intersect(m_Cliprect);
                                if (!wrect.is_empty())
                                    {
                                        rgn.assign_union(wrect);
                                        m_lWList.insert(hwnd);
                                    }
                            }
                    }
                }
            }

            ++iPixelColor; // Next PixelColor in the list
        }
    }
    PixelEngine.ReleaseCapture();
    ///////////////////////
    // We coun the number of idle detects
    // after x time, force some timeout
    if (change_found)
    {
        idle_counter=0;
    }
    else
    {
        idle_counter++;
    }
    if (idle_counter>20) 
    {
        //Beep(100,idle_counter);
        Sleep (idle_counter);
    }
    // 250 increased to 500, possible even 1000 will still have a good reaction time
    if (idle_counter>500) idle_counter=500;
    ///////////////////////

    if (fIncCycle)
    {
       m_nGridCycle = (m_nGridCycle + 1) % (PIXEL_BLOCK_SIZE / GRID_OFFSET);
    }
    return returnvalue;
}

But I think it would be very slow in AutoIt.
 
Although the way the VNC screen capture is quite common:

// Function to capture an area of the screen immediately prior to sending
// an update.
void
vncDesktop::CaptureScreen(const rfb::Rect &rect, BYTE *scrBuff, UINT scrBuffSize,BOOL capture)
{
    assert(rect.enclosed_by(m_bmrect));
    if (capture)
    {
        if (OSversion()==1 || OSversion()==2)
        m_fCaptureAlphaBlending = m_server->CaptureAlphaBlending();


        // Select the memory bitmap into the memory DC
        HBITMAP oldbitmap;
        if ((oldbitmap = (HBITMAP) SelectObject(m_hmemdc, m_membitmap)) == NULL)
            return;

    #if defined(_DEBUG)
        DWORD t = timeGetTime();
    #endif
        // Capture screen into bitmap
        BOOL blitok = BitBlt(m_hmemdc, rect.tl.x, rect.tl.y,
            (rect.br.x-rect.tl.x),
            (rect.br.y-rect.tl.y),
            m_hrootdc, rect.tl.x, rect.tl.y, (m_fCaptureAlphaBlending && !m_Black_window_active) ? (CAPTUREBLT | SRCCOPY) : SRCCOPY);
    #if defined(_DEBUG)
        DWORD e = timeGetTime() - t;
        vnclog.Print(LL_INTWARN, VNCLOG("Blit (%u,%u - %u,%u) (%ux%u took %ums\n"), 
            rect.tl.x, rect.tl.y, rect.br.x, rect.br.y,
            rect.width(), rect.height(), e);
    #endif
    #if 0
        //*******************************
        static int cycle(0);
        static COLORREF c[] = {RGB(0xFF,0,0), RGB(0,0xFF,0),RGB(0,0,0xFF), RGB(0xFF, 0,0xFF), RGB(0,0xFF,0xFF)};
    HPEN pen = CreatePen(PS_SOLID|PS_INSIDEFRAME, 2, c[cycle]);
    HPEN oldpen = (HPEN)SelectObject(m_hmemdc, pen);
    SelectObject(m_hmemdc, GetStockObject(HOLLOW_BRUSH));
    Rectangle(m_hmemdc, rect.tl.x, rect.tl.y, rect.br.x, rect.br.y);
    SelectObject(m_hmemdc, oldpen);
    DeleteObject(pen);
        cycle = (cycle + 1) % (sizeof c / sizeof c[0]);
        //*******************************
    #endif
        // Select the old bitmap back into the memory DC
        SelectObject(m_hmemdc, oldbitmap);

        if (blitok)
        {
            // Copy the new data to the screen buffer (CopyToBuffer optimises this if possible)
            CopyToBuffer(rect, scrBuff, scrBuffSize);
        }
    }
    else
    {
        CopyToBuffer(rect, scrBuff, scrBuffSize);
    }

}

It's basically the same way I use to capture the entire remote screen, and then I capture only the window that the mouse is over, thus gain in performance and saves network bandwidth!

But there's a problem with menus because each submenu is also a window and if the mouse is not over, is not sent!
 
Edit:
This is the snippet I use to capture only the window with the mouse over:
 

; Retrieve the window handle from mouse point.
$hWinFromPnt = DllCall($hUSER32, "hwnd", "WindowFromPoint", "struct", $tPNTStru) ;_WinAPI_WindowFromPoint($tPNTStru)
$hWinFromPnt = $hWinFromPnt[0]

$aWSize = WinGetPos($hWinFromPnt)

; Only the window that the mouse is over is to be sent, it gains in performance and saves the network bandwidth.
If $hWinFromPnt = $hWinFromPnt_Old Then
    If $aWSize[0] < 0 Then
        $aWSize[0] = 0
    EndIf
    If $aWSize[1] < 0 Then
        $aWSize[1] = 0
    EndIf
    If $aWSize[0] + $aWSize[2] > @DesktopWidth Then
        $aWSize[2] = @DesktopWidth - $aWSize[0]
    EndIf
    If $aWSize[1] + $aWSize[3] > @DesktopHeight Then
        $aWSize[3] = @DesktopHeight - $aWSize[1]
    EndIf

    ; If the window is being moved, a margin is added to erase the traces left by movement,
    ; since only she is being sent to the remote computer!
    If $isWinMove Then
        $isWinMove = 0
        $aWSize[0] -= ($aWSize[2] / 4)
        $aWSize[1] -= ($aWSize[3] / 4)
        $aWSize[2] += ($aWSize[2] / 2)
        $aWSize[3] += ($aWSize[3] / 2)
    EndIf

    $iWndX = ($aWSize[0] / @DesktopWidth) * $ScrWidth
    $iWndY = ($aWSize[1] / @DesktopHeight) * $ScrHeight
    $iWndW = ($aWSize[2] / @DesktopWidth) * $ScrWidth
    $iWndH = ($aWSize[3] / @DesktopHeight) * $ScrHeight
Else
    ; If the current window is different from the previous, the entire screen will be sent to the remote computer!
    $aWSize[0] = 0
    $aWSize[1] = 0
    $aWSize[2] = @DesktopWidth
    $aWSize[3] = @DesktopHeight
    $ScrnBufRefresh = 1
    $hWinFromPnt_Old = $hWinFromPnt
EndIf

;----> Create bitmap according to the current window size
$hHBitmap2 = _CreateDibBitmap($iWndW, $iWndH, $iScrBits, $pBits2, $tBMPINFO2, $hDIB_DC2)

;_WinAPI_StretchBlt($hDIB_DC2, 0, 0, $iWndW, $iWndH, $hDeskDC, $aWSize[0], $aWSize[1], $aWSize[2], $aWSize[3], BitOR($SRCCOPY, $CAPTUREBLT))
DllCall($hGDIP32, 'bool', 'StretchBlt', _
        'handle', $hDIB_DC2, _
        'int', 0, _
        'int', 0, _
        'int', $iWndW, _
        'int', $iWndH, _
        'hwnd', $hDeskDC, _
        'int', $aWSize[0], _
        'int', $aWSize[1], _
        'int', $aWSize[2], _
        'int', $aWSize[3], _
        'dword', BitOR($SRCCOPY, $CAPTUREBLT))

 
JS

Edited by JScript

http://forum.autoitbrasil.com/ (AutoIt v3 Brazil!!!)

Somewhere Out ThereJames Ingram

somewh10.png

dropbo10.pngDownload Dropbox - Simplify your life!
Your virtual HD wherever you go, anywhere!

Share this post


Link to post
Share on other sites

But there's a problem with menus because each submenu is also a window and if the mouse is not over, is not sent!

Why is that a problem? Because you can't see what you're doing when you control it with the keyboard? That would be true with every window, not just menus. Solution = send the active window too.

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

There is no problem in sending only windows that are no menus, but with windows menu is quite different, see:

hkIjwFO.png

Remember that only the window with the mouse is over it is sent!

Send the active window would be a solution too, any idea code for this? I tried with _WinAPI_EnumWindows(), but I found very slow...

JS

Edited by JScript

http://forum.autoitbrasil.com/ (AutoIt v3 Brazil!!!)

Somewhere Out ThereJames Ingram

somewh10.png

dropbo10.pngDownload Dropbox - Simplify your life!
Your virtual HD wherever you go, anywhere!

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

See:
N4sc4LO.png

Observe that the mouse pointer is over a window, only then it is sent to the remote computer, but if the client move the mouse down a bit, will stay on top of another window that represents the menu that opened!

Your idea of ​​sending the window that is active also serves to the menu because it is a "window"!

Edit:

If I use the code below, I can send the active window, in the case the menu is opened:

$aEnumWin = _WinAPI_EnumWindows()
If $aEnumWin_Old <> $aEnumWin Then
    $aEnumWin_Old = $aEnumWin
    $hWinFromPnt = $aEnumWin[1][0]
Else
    ; Retrieve the window handle from mouse point.
    $hWinFromPnt = _WinAPI_WindowFromPoint($tPNTStru)
    $hWinFromPnt = $hWinFromPnt[0]
EndIf

$aWSize = WinGetPos($hWinFromPnt)

The result is:
intxoRo.png

But _WinAPI_EnumWindows() function is slow and has items that I do not need such as: Window class name

JS

Edited by JScript

http://forum.autoitbrasil.com/ (AutoIt v3 Brazil!!!)

Somewhere Out ThereJames Ingram

somewh10.png

dropbo10.pngDownload Dropbox - Simplify your life!
Your virtual HD wherever you go, anywhere!

Share this post


Link to post
Share on other sites

Not yet, the code is a bit disorganized and there are still several things such as language support!

Soon I will update the download ok?

What part do not you understand?

JS


http://forum.autoitbrasil.com/ (AutoIt v3 Brazil!!!)

Somewhere Out ThereJames Ingram

somewh10.png

dropbo10.pngDownload Dropbox - Simplify your life!
Your virtual HD wherever you go, anywhere!

Share this post


Link to post
Share on other sites

After a search for functions in the help file, I found this: _WinAPI_TransparentBlt()

I did some testing but I do not have much knowledge in GDI, if someone could give a hint on how to proceed.

JS


http://forum.autoitbrasil.com/ (AutoIt v3 Brazil!!!)

Somewhere Out ThereJames Ingram

somewh10.png

dropbo10.pngDownload Dropbox - Simplify your life!
Your virtual HD wherever you go, anywhere!

Share this post


Link to post
Share on other sites

Sorry, my English is bad.

Please check whether the code used _WinAPI_PrintWindow ()

If so, please try try to replace other methods

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0