Здравствуйте, подскажите возможно ли такое... Вообщем в программе в функции обработки сообщений окна обработчик WM_PAINT следущего вида: Код (Text): case WM_PAINT: { hdc = BeginPaint(hwnd, &ps); EndPaint(hwnd, &ps); } break; В другом обработчике, например, WM_COMMAND вызываю TextOut (GetDC и ReleaseDC тоже всё как положено), но как только окно перекрывается другим или выходит за пределы экрана текст стирается... Возможно ли сделать так чтобы текст не стирался при манипуляции с окном, но не трограя обработчик WM_PAINT? (ну или на крайний случай трогая) P/S: припоминаю, что что то надо мутить с виртуальными окнами...
в WM_PAINT как раз и надо прорисовывать всё. перемести туда вызов TextOut. точнее, сделай вывод по флагу. а флаг ставишь в WM_COMMAND когда окно затирается другими, вызывается именно WM_PAINT. так что рисовать все нужно там. а что рисовать - это уже надо думать если очень хочется рисовать из разных мест, делай в WM_PAINT отрисовку какогонибудь Bitmap-а временного в памяти, А из других мест рисуй в этот битмап и делай инвалидейт виндоу
Создаётся DC с помощью CreateCompatibleDC, в разных частях программы рисуется в него, а в WM_PAINT делается BitBlt. А чтобы сразу после отрисовки отобразилась новая картинко, делается InvalidateRect.
Great и Booster спасибо за ответы, но немогу понять, чего то я туплю =) У меня нарушение доступа выскакивает когда строку получаю в другом обработчике, а вывожу текст в WM_PAINT. Поэтому и решил в WM_PAINT не соваться, а сделать так... Вот кусок проги... Код (Text): LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; static char mystring[31]; switch(message) { case WM_PAINT: { hdc = BeginPaint(hwnd, &ps); EndPaint(hwnd, &ps); } break; case WM_COMMAND: switch (LOWORD(wParam)) { case BN_CLICKED: if (hButton == (HWND)lParam) { hdc = GetDC (hwnd); // // // // [b]ЗДЕСЬ ВСЯКИЕ МАТЕМАТИЧЕСКИЕ[/b] [b]РАСЧЁТЫ[/b] // // // // // memset (mystring, 0, sizeof(mystring)); wsprintf (mystring, "Диаметр окружности: %d", counter); TextOut(hdc, 10, 120, mystring, strlen(mystring)); ReleaseDC (hwnd, hdc); DeleteDC (hdc); } }break; } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, message, wParam, lParam); } return 0; }
glukker Конечно это не верно, так как когда придёт WM_PAINT, придёт трындец. Access Violation надо бороть. А текст и не надо выводить в WM_PAINT, выводить надо задний DC, как я описал выше.
А вот этого DeleteDC (hdc) не надо. А если WM_PAINT не трогать, то так: Код (Text): invoke LoadBitmap,hInstance,20 mov hBMP, eax invoke CreatePatternBrush,hBMP mov hBrush, eax invoke SetClassLong,hWin,GCL_HBRBACKGROUND,hBrush в этом случае система сама будет прорисовывать указанный hBrush. Не юзал с динамическим содержанием, но статической картинкой, выходит хорошо.
Что то пока как то не очень получается Вообще не выводит ничего... Код (Text): LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc, hMemDC; static char mystring[31]; switch(message) { case WM_PAINT: { hdc = BeginPaint(hwnd, &ps); //а в WM_PAINT делается BitBlt. BitBlt ( hdc, 0, 0, 500, 300, hMemDC, 0, 0, SRCCOPY ); EndPaint(hwnd, &ps); } break; case WM_COMMAND: switch (LOWORD(wParam)) { case BN_CLICKED: if (hButton == (HWND)lParam) { hdc = GetDC (hwnd); //Создаётся DC с помощью CreateCompatibleDC hMemDC = CreateCompatibleDC(hdc); // // // ЗДЕСЬ ВСЯКИЕ МАТЕМАТИЧЕСКИЕ // РАСЧЁТЫ // // memset (mystring, 0, sizeof(mystring)); wsprintf (mystring, "Диаметр окружности: %d", counter); //в разных частях программы рисуется в него TextOut(hMemDC, 10, 120, mystring, strlen(mystring)); //А чтобы сразу после отрисовки отобразилась новая картинко, делается InvalidateRect. InvalidateRect(hwnd, NULL, true); ReleaseDC (hwnd, hdc); DeleteDC (hdc); } }break; } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, message, wParam, lParam); } return 0; }
Во первых делаем: Код (Text): static HDC hMemDC; Во вторых надо ещё сделать: Код (Text): static HBITMAP hBitm; hBitm = CreateCompatibleBitmap(hdc, xSize, ySize); SelectObject(hMemDC, bitm); Так же желательно, но не обязательно создать всякие HPEN, HBRUSH, HFONT, c помощью CreatePen, CreateSolidBrush и CreateFontA. А также выбрать их - SelectObject(hMemDC, hPen) и т.д для всего хозяйства. После всей инициализации DС, можно сделать очистку фона например в белый цет. Код (Text): hBrush = CreateSolidBrush(0xffffff); FillRect(hMemDC, &rect, hBrush); Да и инициализацию лучше делать в WM_CREATE.
Booster можете посмотреть пожалуйста? Я файл проекта скинул на ifolder... http://stream.ifolder.ru/7269459
glukker Код (Text): hBitm = CreateCompatibleBitmap (hdc, 500, 300); SelectObject (hMemDC, hBitm); Перенеси из WM_PAINT, в WM_COMMAND. Создавать каждый раз новый битмап в WM_PAINT не стоит. А вообще вот это дело: Код (Text): hdc = GetDC (hwnd); hMemDC = CreateCompatibleDC (hdc); hBitm = CreateCompatibleBitmap (hdc, 500, 300); SelectObject (hMemDC, hBitm); ReleaseDC (hwnd, hdc); Надо перенести в WM_CREATE, по нажатию кнопки только пиши текст. DeleteDC (hdc); - не нужен, удали его.
А как его можно перенести в WM_CREATE, если оно обрабатывается при создании окна... А выводить TextOut'ом нужно каждый раз когда на кнопку давить буду????
Поправился, это конечно в обработчике. Код (Text): TextOut(hMemDC, 10, 10, "1234567890", 10); InvalidateRect(hwnd, NULL, true); Остальное, то есть инициализацию в WM_CREATE. Контекст в памяти и остальную лабуду (шрифты и прочее) нужно создавать один раз, при создании окна.
А ещё вопрос чтобы не париться с размерами в функции CreateCompatibleBitmap как можно получить эти размеры, а то мало ли окно размер поменяет да и смотрится так кривовато...
Глубоко не вдавался в этот вопрос, просто делал размером максимально возможного для окно. Можно наверно ещё пересоздавать в WM_SIZE и например копировать старый в новый.
Вообще Booster спасибо за помощь всё выводит и не затирается, но после нажатия на кнопку всё окно становится чёрного цвета, почему? Код (Text): LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; static HDC hMemDC; static HBITMAP hBitm; switch(message) { case WM_PAINT: { hdc = BeginPaint(hwnd, &ps); BitBlt (hdc, 0, 0, iWinX, iWinY, hMemDC, 0, 0, SRCCOPY); EndPaint(hwnd, &ps); } break; case WM_COMMAND: switch (LOWORD(wParam)) { case BN_CLICKED: if (hButton == (HWND)lParam) { hdc = GetDC (hwnd); hMemDC = CreateCompatibleDC (hdc); hBitm = CreateCompatibleBitmap (hdc, iWinX, iWinY); SelectObject (hMemDC, hBitm); TextOut(hMemDC, 10, 120, "1234567890", 10); InvalidateRect(hwnd, NULL, true); ReleaseDC (hwnd, hdc); DeleteDC (hdc); } }break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, message, wParam, lParam); } return 0; }
glukker Дело в том, что когда вызывается Инвалидейт, окну приходит сообщение WM_PAINT, и WindowFunc вызывается ещё раз, причём со своим кадром стэка, отличным от кадра той функции, из-под к-рой был сопстно вызван InvalidateRect. Немудрено что hMemDC содержит какуюнить хрень, к делу отношения не имеющую =) Впрочем, я С не знаю, и утверждать наверняка не берусь. Что-то смущает меня директива static. ++ а битмап надобы освободить... да и DC из-под него тоже.
Это мне посоветовали делать (товарищ Booster), правда я и сам кое где видел такое... Все разобрался причина была в отсутствии следущего кода: Код (Text): hBrush = CreateSolidBrush (0xFFFFFF); SetRect (&Rect, 0, 0, iWinX, iWinY); FillRect (hMemDC, &Rect, hBrush);
Вот кому интересно полный рабочий код окно которое не затирает выводимый текст... Код (Text): LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; static HDC hMemDC; static HBITMAP hBitm; HBRUSH hBrush; RECT Rect; switch(message) { case WM_PAINT: { hdc = BeginPaint(hwnd, &ps); BitBlt (hdc, 0, 0, iWinX, iWinY, hMemDC, 0, 0, SRCCOPY); EndPaint(hwnd, &ps); } break; case WM_COMMAND: switch (LOWORD(wParam)) { case BN_CLICKED: if (hButton == (HWND)lParam) { hdc = GetDC (hwnd); hMemDC = CreateCompatibleDC (hdc); hBitm = CreateCompatibleBitmap (hdc, iWinX, iWinY); SelectObject (hMemDC, hBitm); hBrush = CreateSolidBrush (0xFFFFFF); SetRect (&Rect, 0, 0, iWinX, iWinY); FillRect (hMemDC, &Rect, hBrush); TextOut(hMemDC, 10, 120, "1234567890", 10); InvalidateRect(hwnd, NULL, true); ReleaseDC (hwnd, hdc); DeleteDC (hdc); } }break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, message, wParam, lParam); } return 0; }