«PrintScreen»: 256 цветов, logoff

Тема в разделе "WASM.WIN32", создана пользователем sarin, 8 фев 2009.

  1. sarin

    sarin Member

    Публикаций:
    0
    Регистрация:
    2 июн 2005
    Сообщения:
    30
    Потребовалось сделать программку повторяющую функционал кнопки «PrintScreen» - считать битмэп рабочего стола в память.
    Делалось так (упрощённо):
    Код (Text):
    1. BITMAPINFO bi;
    2. ...
    3. ...
    4. dc = CreateDC ("DISPLAY", NULL, NULL, NULL);    // или dc = GetDC(GetDesktopWindow());
    5. mdc = CreateCompatibleDC (dc);
    6.  
    7. X_MAX = GetSystemMetrics (SM_CXSCREEN);
    8. Y_MAX = GetSystemMetrics (SM_CYSCREEN);
    9. BPP = (unsigned short) GetDeviceCaps (dc, BITSPIXEL);
    10. if (BPP == 32) BPP = 24; // экономим память. :)
    11. PLS = (unsigned short) GetDeviceCaps (dc, PLANES); BPP *= PLS;
    12. i = ((X_MAX * tBPP / 8) * Y_MAX);
    13. if (tBPP <= 8)
    14. {
    15. nColors = (unsigned short) (1 << tBPP);
    16. i += (nColors << 2);
    17. }
    18. hMem = GlobalAlloc (GPTR, i);
    19. if (hMem == 0) return;
    20. bbuff = GlobalLock (hMem);
    21. if (bbuff == 0) return;
    22. bi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
    23. bi.bmiHeader.biWidth = X_MAX;
    24. bi.bmiHeader.biHeight = Y_MAX;
    25. bi.bmiHeader.biPlanes = 1;
    26. bi.bmiHeader.biBitCount = tBPP;
    27. bi.bmiHeader.biCompression = BI_RGB;
    28. if (tBPP <= 8)
    29. {
    30. pLogPal = malloc (sizeof (LOGPALETTE) + (nColors * sizeof (PALETTEENTRY)));
    31. pLogPal->palVersion = 0x300;
    32. pLogPal->palNumEntries = nColors;
    33. }
    34. hbm = CreateCompatibleBitmap (dc, X_MAX, Y_MAX);
    35. if (tBPP == 8)
    36. {
    37. GetSystemPaletteEntries(dc,0,nColors,pLogPal->palPalEntry);  
    38. for (p=0;p<(nColors-20);p++) pLogPal->palPalEntry[p+10].peFlags = PC_NOCOLLAPSE;
    39. hPal = CreatePalette(pLogPal);
    40. SelectPalette(mdc,hPal,FALSE); RealizePalette(mdc);
    41. }
    42. ohbm = SelectObject (mdc, hbm);
    43. BitBlt (mdc, 0, 0, X_MAX, Y_MAX, dc, 0, 0, SRCCOPY);
    44. SelectObject (mdc, ohbm);
    45. if (GetDIBits(mdc, hbm, 0, Y_MAX, bbuff, (LPBITMAPINFO) & bi,DIB_RGB_COLORS) != Y_MAX) return 0;
    Пока тестилось на 32/24/16/4/1 бит цвете всё было OK. А в 256-цветах (8 бит) – частично "бились" значения в получаемой палитре (bi.bmiColors) – обычно последние 10 записей и из-за этого картинка искажается. По документации MSDN известно что системная т.е. неизменяемая часть палитры состоит из 20 цветов (записи 0..9, 246..255). Для исправления этой ошибки всем несистемным цветам ставится флаг PC_NOCOLLAPSE.

    1) Как реализовать функционал «PrintScreen», если пользователь вышел из cистемы?
     
  2. sarin

    sarin Member

    Публикаций:
    0
    Регистрация:
    2 июн 2005
    Сообщения:
    30
    И ещё вопросик.

    Разрешение 720x576x24.
    Выделяю память на битмэп.
    720 * 3 * 30 = 64800 байт (30 строк)
    Делаю так
    Код (Text):
    1. s = 30;
    2. if (GetDIBits(dc,hbm,0,s,buffer,(LPBITMAPINFO)&bi,DIB_RGB_COLORS) != s)
    3. MessageBox( thiswnd, "GetDIBits() fails", "", MB_OK );
    При s = 30,29,28,27 всё работает но в taskmanager-е видно что происходит page fault. А при s <= 26 всё работает без page fault. Что это за бред и как отловить page fault в т.ч. и в других программах?
     
  3. murder

    murder Member

    Публикаций:
    0
    Регистрация:
    3 июн 2007
    Сообщения:
    628
  4. sarin

    sarin Member

    Публикаций:
    0
    Регистрация:
    2 июн 2005
    Сообщения:
    30
    Актуально. Т.е. когда юзер выходит из системы, функции GetDIBits() и BitBlt() возвращают ошибки или пустой черный экран. Нужны привилегии системы? Запускать прогу как службу или что-то ещё?
     
  5. ASMatic

    ASMatic New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2010
    Сообщения:
    233
    виден другой десктоп, т.е вам нужно переключить тред на другой десктоп (винлогона) и оттуда сделать снимок.