Hey, I have a big problem. I want to do a program which will get a part of the screen of a program. After that It will show this small rectangle in Image component in BCB. But the problem is, it has to refresh it at least 10 times in one second. For now I succeeded in doing a code that gets a screen but it is too slow. For now it is refreshing in 2,5-3 seconds:/ Maybe better solution would be DirectX or something else?

Image1->Picture->LoadFromFile("black.bmp");
         Image1->Refresh();
         HWND Wnd=FindWindow(NULL,"Window");
         if(Wnd==0) {MessageBox(0,"Didnt find the window",0,0);}
         HDC ekran=GetDC(Wnd);
         for(int i=0; i<116; i++)
         {
           for(int j=0; j<114; j++)
           {
               screen[i][j]=GetPixel(ekran, 674+i,11+j);   //colorref
               Image1->Picture->Bitmap->Canvas->Pixels[i][j]=screen[i][j];
           }
         }

Dani AI

Generated

Quick diagnosis and the immediate cause of the black output: in ’s second snippet a memory DC and bitmap are created and then immediately used as the BitBlt source. That copies an uninitialized (black) bitmap to the target. ’s suggestion to use BitBlt is right — BitBlt (or a DIB-based transfer) is the right approach for bulk copies and will be orders of magnitude faster than per-pixel GetPixel loops.

Correct capture sequence (summary)

  • Create a memory DC compatible with the window DC.
  • Create a DIBSection (or compatible bitmap) and SelectObject it into the memory DC.
  • BitBlt from the window DC INTO the memory DC (this fills the bitmap).
  • Copy the DIB memory into a VCL TBitmap (memcpy per scanline) or use GetDIBits/SetDIBits.
  • Restore the old bitmap into the DC, then delete/cleanup.

Example sketch (C++ style) showing the DIBSection approach:

HDC hWndDC = GetDC(hWnd);
HDC memDC  = CreateCompatibleDC(hWndDC);

BITMAPINFO bi = {};
bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
bi.bmiHeader.biWidth = w;
bi.bmiHeader.biHeight = -h;       // top-down for easy ScanLine copy
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;

void *pixels = nullptr;
HBITMAP hDIB = CreateDIBSection(hWndDC, &bi, DIB_RGB_COLORS, &pixels, NULL, 0);
HBITMAP old = (HBITMAP)SelectObject(memDC, hDIB);

BitBlt(memDC, 0,0, w,h, hWndDC, srcX,srcY, SRCCOPY);

// memcpy per-scanline from 'pixels' into TBitmap->ScanLine[y]
// cleanup: SelectObject(memDC, old); DeleteObject(hDIB); DeleteDC(memDC); ReleaseDC(hWnd, hWndDC);

Performance & reliability tips

  • Do not use GetPixel or Canvas->Pixels for full rectangles. Use BitBlt + DIBSection + memcpy/GetDIBits.
  • Reuse the DC and HBITMAP between frames; creating/deleting on every frame kills FPS.
  • Run capture in a background thread timed at ~100 ms (10 FPS). Update the UI (TImage->Picture->Bitmap->Assign) on the main thread via Synchronize/Queue or PostMessage.
  • Minimized/off-screen or hardware-accelerated (DirectX) windows can return black. Try PrintWindow for GDI apps; for games consider DX Desktop Duplication (Windows 8+) or capturing via the app’s DirectX surfaces.

Checklist: flip BitBlt source/destination as above, reuse buffers, copy via DIB memory (not per-pixel), and update the VCL image from the UI thread.

Recommended Answers

All 2 Replies

Now I have something like this. It is within a loop. It should show the window but it shows only black screen. When I'm using analogical code but with loading a bitmap from file everthing works fine.
1.

HDC WinDC;
 HDC CopyDC;
 HBITMAP hBitmap;
 RECT rt;
 HWND Wnd=FindWindow(NULL,"WINDOW");
 if(Wnd==0) {MessageBox(0,"didnt found the window!",0,0);}
 GetWindowRect (Wnd, &rt);
 WinDC = GetDC (Wnd);
 CopyDC = CreateCompatibleDC (global_hdc);
 std::cout<<rt.right - rt.left<<std::endl;
 std::cout<<rt.bottom - rt.top<<std::endl;
 hBitmap = CreateCompatibleBitmap (WinDC,
 	800, //width
 	600);//height
SelectObject (CopyDC, hBitmap);
BitBlt (global_hdc,   //destination
	0,0,
	800, //width
	600, //height
 	CopyDC,    //source
 	0, 0,
 	SRCCOPY);

DeleteObject((HBITMAP)hBitmap);
DeleteDC(CopyDC);

2.Analogical code with loading from file:

HBITMAP image;
BITMAP bm;
HDC hdcMem;
//load the bitmap image
image = (HBITMAP)LoadImage(0,"asteroid.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
//read the bitmap's properties
GetObject(image, sizeof(BITMAP), &bm);
//create a device context for the bitmap
hdcMem = CreateCompatibleDC(global_hdc);
SelectObject(hdcMem, image);
//draw the bitmap to the window (bit block transfer)
BitBlt(
global_hdc, //destination device context
0, 0, //x,y location on destination
bm.bmWidth, bm.bmHeight, //width,height of source bitmap
hdcMem, //source bitmap device context
0, 0, //start x,y on source bitmap
SRCCOPY); //blit method
//delete the device context and bitmap
DeleteDC(hdcMem);
DeleteObject((HBITMAP)image);
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.