Я пытаюсь создать простой маленький инструмент, который позволил бы пользователю переключаться из обычной работы в режим, в котором все сообщения приложения отключены, и они могут использовать мышь для рисования от руки, а затем снова переключать режимы, чтобы сохранитьих рисование на экране, в то время как они делают любые другие нормальные вещи, которые они хотят.Это может, если я решу, превратиться в приятную вещь, которую вы можете использовать для использования декорированного экрана, сохранив сделанные вами декорации и загрузив их позже.
Когда я начал это (что было более полугода назад,вскоре после обнаружения Windows API) я просто сделал глобальное отслеживание мыши и нарисовал круг, где бы он ни был, для GetDC (NULL) HDC.Проблемы, конечно, заключались в том, что оно исчезало, когда что-либо под ним обновлялось, и по-прежнему пропускались сообщения мыши, поэтому, если бы я, например, удерживал кнопку на рабочем столе, это повлияло бы на прямоугольники с изменяющимися размерами.
Сегодня, после того, как у меня наконец-то появилось свободное время, прошедшее после последней крупной работы над этим большую часть того, что было 6 месяцев назад, я решил переделать его и посмотреть, смогу ли я достичь того, чего хотел.Я сделал прозрачное, самое верхнее, многоуровневое, многоуровневое окно WS_CHILD (в основном экран не меняется, но есть окно поверх всего, что пропускает сообщения).Затем я сделал так, чтобы в режиме рисования значение альфа-канала было установлено равным 1, и пользователь мог рисовать.Пока я этого не осознал, я понял, что, поскольку альфа-значение окна равно 1, рисование не будет видно.
Затем я попытался использовать GetDC (NULL), но вспомнил, чтостирается, когда что-то обновляется.
Теперь я просто подумал об использовании растровых изображений и dcs для многократного сохранения экрана в dc, рисования на другом dc, а затем копирования его обратно на тот, на котором сохранен экран с прозрачностью длячасти, которые не нарисованы, и скопируйте их обратно на экран, но я отчаиваюсь.Вот мой исходный код для этого (функция маски взята из этого урока ).Пожалуйста, скажите мне, если что-то из этого не нужно.Я использовал точечные рисунки для двойной буферизации, но я не совсем уверен, где они мне нужны.
//Global mask since it takes longer to make
HBITMAP mask;
//Window Procedure Start
HDC screenDC; //hdc for entire screen
screenDC = GetDC (NULL); //get DC for screen
HDC memDC = CreateCompatibleDC (screenDC); //create DC for holding the screen+paint
HBITMAP bm = CreateCompatibleBitmap (screenDC, GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN)); //create bitmap for memDC
HDC paintDC = CreateCompatibleDC (screenDC); //create DC to paint on
HBITMAP paintBM = CreateCompatibleBitmap (screenDC, GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN)); //create bitmap for paintDC
SelectObject (memDC, bm); //select bitmap into memDC
SelectObject (paintDC, paintBM); //select painting bitmap into paintDC
BitBlt (memDC, 0, 0, GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN), screenDC, 0, 0, SRCCOPY); //copy screen to memDC
SetBkColor (paintDC, RGB(0,0,0)); //set background of paintDC to black so it's all transparent to start
//WM_CREATE
mask = CreateBitmapMask (bm, RGB(0,0,0)); //create black mask (paint colours are limited 1-255 now)
//painting is done into paintDC
//at end of Window Procedure
SelectObject (paintDC, mask); //select mask into paintDC
BitBlt (memDC, 0, 0, GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN), paintDC, 0, 0, SRCAND); //this in combination with the next should make it bitblt with all of the black taken out I thought
SelectObject (paintDC, paintBM); //select bitmaps into DCs
SelectObject (memDC, bm);
BitBlt (memDC, 0, 0, GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN), paintDC, 0, 0, SRCPAINT); //second part of transparent bitblt
BitBlt (screenDC, 0, 0, GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN), paintDC, 0, 0, SRCCOPY); //copy memDC back to screen
DeleteObject (paintBM); //delete stuff
DeleteObject (mask);
DeleteDC (memDC);
DeleteDC (paintDC);
ReleaseDC (hwnd, screenDC);
//CreateBitmapMask() (taken directly from http://www.winprog.org/tutorial/transparency.html
HBITMAP CreateBitmapMask(HBITMAP hbmColour, COLORREF crTransparent)
{
HDC hdcMem, hdcMem2;
HBITMAP hbmMask;
BITMAP bm;
// Create monochrome (1 bit) mask bitmap.
GetObject(hbmColour, sizeof(BITMAP), &bm);
hbmMask = CreateBitmap(bm.bmWidth, bm.bmHeight, 1, 1, NULL);
// Get some HDCs that are compatible with the display driver
hdcMem = CreateCompatibleDC(0);
hdcMem2 = CreateCompatibleDC(0);
SelectObject(hdcMem, hbmColour);
SelectObject(hdcMem2, hbmMask);
// Set the background colour of the colour image to the colour
// you want to be transparent.
SetBkColor(hdcMem, crTransparent);
// Copy the bits from the colour image to the B+W mask... everything
// with the background colour ends up white while everythig else ends up
// black...Just what we wanted.
BitBlt(hdcMem2, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
// Take our new mask and use it to turn the transparent colour in our
// original colour image to black so the transparency effect will
// work right.
BitBlt(hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem2, 0, 0, SRCINVERT);
// Clean up.
DeleteDC(hdcMem);
DeleteDC(hdcMem2);
return hbmMask;
}
Я знаю, что код вполне может быть ужасным.Я принимаю во внимание все предложения, просто я не слишком разбираюсь в этом вопросе и не понимаю всего, что происходит, что затрудняет исправление.Этот код запускается для меня тем, что я очень часто ставлю полноэкранный черный прямоугольник.
Мой главный вопрос: есть ли способ рисовать на экране, не стирая его при обновлении окон?Единственная реальная вещь, о которой я могу думать сейчас, - это хранить все местоположений крошечных отрезков, которые рисует пользователь, и продолжать перерисовывать их в верхней части экрана.На первый взгляд это кажется очень неэффективным и расточительным в памяти.
Кроме того, я был совершенно уверен, когда писал это, что мне не нужны были примеры кода для теоретических вещей до поставляемых фрагментов кода.Большая часть этого уже исчезла, но на самом деле это больше теоретический вопрос.
РЕДАКТИРОВАТЬ: я только что узнал о функции TransparentBlt, которая казалась идеальной для ситуации, поэтому я попытался использовать ее вместо SRCPAINT иSRCAND BitBlts, и он дал тот же результат: черный прямоугольник, закрывающий экран, иногда исчезают части, когда моя мышь перемещается по вещам.