Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: При перекрытии окна другими окнами исчезает нарисованное... Как быть?  (Прочитано 15743 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Topic
Интересующийся

ru
Offline Offline

« : 14-08-2010 17:55 » 

При перекрытии окна другими окнами исчезает нарисованное... Как быть?
Я рисую сначала в MemDC, потом то, что получилось отправляю в HDC.
При перемещении окна нарисованное не пропадает, а при перекрытии/выходе окна за пределы монитора/свертывании/развертывании/изменении размеров окна - при всё при этом исчезает нарисованное.
Почему при этих действиях не вызывается WM_PAINT? Как перерисовать?

Код:
//#include <windows.h>
#include "KWnd.h"

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{

MSG msg;
KWnd mainWnd(TEXT("An application"), hInstance, nShowCmd, WndProc);

while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
RECT rect;
static HDC hMemDC;

int xrand;
int yrand;

int Rrand;
int Grand;
int Brand;
int iWidthRand;
int iStyleRand;

HPEN myPen;

switch(uMsg)
{
case WM_CREATE:

hDC = GetDC(hWnd);
hMemDC = CreateCompatibleDC(hDC);
break;

case WM_PAINT:

hDC = BeginPaint(hWnd, &ps);
GetClientRect(hWnd, &rect);
// Теперь копируем растр из памяти на экран
BitBlt(hDC, 0, 0, rect.right, rect.bottom, hMemDC, 0, 0, SRCCOPY);
EndPaint(hWnd, &ps);
break;

case WM_LBUTTONDOWN:

hDC = GetDC(hWnd);
if (hDC)
{
// рисуем что требуется
MoveToEx(hDC, 50, 60, NULL);
GetClientRect(hWnd, &rect);

for (int i=0; i<10; i++)
{
// позиция по х и у, куда проводить линию
xrand = rand()%(rect.right-100)+50;
yrand = rand()%(rect.bottom-100)+50;

// стиль (начертание) линии
iStyleRand = rand()%7;

// толщина линии
iWidthRand = rand()%7;

// цвет линии
Rrand = rand()%256;
Grand = rand()%256;
Brand = rand()%256;

// создаем карандаш
myPen = CreatePen(iStyleRand, iWidthRand, RGB(Rrand, Grand, Brand));

// выбираем наш карандаш
SelectObject(hDC, myPen);

// нарисовать линию
LineTo(hDC, xrand, yrand);

// освобождаем память из под созданного карандаша
DeleteObject(myPen);
}

// освобождаем контекст
ReleaseDC(hWnd, hDC);
}

break;

case WM_DESTROY:
DeleteDC(hMemDC);
PostQuitMessage(0);
break;

default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

return 0;
}

Тут создание окна, ничего интересного:
Код:
#include <windows.h>

class KWnd
{
public:
KWnd(LPCTSTR windowName, HINSTANCE hInst, int cmdShow,
LRESULT (WINAPI *pWndProc)(HWND, UINT, WPARAM, LPARAM),
LPCTSTR menuname = NULL,
int x = CW_USEDEFAULT, int y = 0,
int width = CW_USEDEFAULT, int height = 0,
UINT classStyle = CS_HREDRAW | CS_VREDRAW,
DWORD windowStyle = WS_OVERLAPPEDWINDOW,
HWND hParent = NULL);

HWND GetHWnd() { return hWnd; }
protected:
HWND hWnd;
WNDCLASSEX wc;
};


KWnd::KWnd(LPCTSTR windowName, HINSTANCE hInst, int cmdShow,
   LRESULT (WINAPI *pWndProc)(HWND, UINT, WPARAM, LPARAM),
   LPCTSTR menuName, int x, int y, int width, int height,
   UINT classStyle, DWORD windowStyle, HWND hParent)
{
TCHAR szClassName[] = TEXT("KWndClass");

wc.cbSize = sizeof(wc);
wc.style = classStyle;
wc.lpfnWndProc = pWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
//wc.hbrBackground = (HBRUSH)GetStockObject(COLOR_APPWORKSPACE+1);
//wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = menuName;
wc.lpszClassName = szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);


if (!RegisterClassEx(&wc))
{
TCHAR msg[100] = TEXT("Cannot register class: ");
wcscat_s(msg, 100, szClassName);
MessageBox(NULL, msg, TEXT("Error"), MB_OK | MB_ICONERROR);
return;
}

// по умолчанию окно располагается по центру
// и имеет фиксированную высоту/ширину
if (x == CW_USEDEFAULT && width == CW_USEDEFAULT)
{
// получаем разрешение монитора (1024х768)
int xFullScreen = GetSystemMetrics(SM_CXSCREEN);
int yFullScreen = GetSystemMetrics(SM_CYSCREEN);

// размеры окна по умолчанию
width  = 720;
height = 540;

// вычисляем позицию левого верхнего угла окна
x = int(xFullScreen/2 - width/2);
y = int(yFullScreen/2 - height/2);
}

hWnd = CreateWindow(szClassName, windowName, windowStyle,
x, y, width, height, hParent, (HMENU)NULL, hInst, NULL);

if (!hWnd)
{
TCHAR text[100] = TEXT("Cannot create window: ");
wcscat_s(text, 100, szClassName);
MessageBox(NULL, text, TEXT("Error"), MB_OK | MB_ICONERROR);
return;
}

ShowWindow(hWnd, cmdShow);
UpdateWindow(hWnd);
}
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #1 : 14-08-2010 18:16 » 

Topic, прицепи проект
Записан

lapulya
Молодой специалист

ru
Offline Offline

« Ответ #2 : 14-08-2010 19:15 » 

так и должно быть насколько я помню, надо в сторону draw смотреть
Записан

С уважением Lapulya
Topic
Интересующийся

ru
Offline Offline

« Ответ #3 : 14-08-2010 19:25 » 

Выкладываю файл на ифолдер (так как сюда не лезет более 1 Мб)
http://ifolder.ru/18896019
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #4 : 14-08-2010 19:35 » 

Topic, удали из проекта папки release и debug, а также файл *.ncb . Будет пара десятков килобайтов ) Что-то не хочется на этот глючный айфолдер лезть
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #5 : 14-08-2010 19:38 » 

ладно уж... Скачал ) Щас поковыряюся
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #6 : 14-08-2010 19:45 » 

Первый же эксперимент
Код:
	case WM_PAINT:
{

hDC = BeginPaint(hWnd, &ps);
GetClientRect(hWnd, &rect);

// // Теперь копируем растр из памяти на экран
// BitBlt(hDC, 0, 0, rect.right, rect.bottom, hMemDC, 0, 0, SRCCOPY);

SetPixel(hDC,20,20,0);

EndPaint(hWnd, &ps);
}
break;

показал, что сообщение WM_PAINT приходит исправно, значит, дело в несинхронизированном заполнении hMemDC
Попытаюсь найти...
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #7 : 14-08-2010 20:09 » 

Я переделал, теперь работает. А красиво, кстати ))) Я щас ещё таймер прилеплю по правой кнопке и выложу )))
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #8 : 14-08-2010 20:23 » 

держи )

Теперь картинка меняется по левому щелчку, а по правому - анимируется. Если снова правой щёлкнуть - снова замрёт

На анимации видно, что начальная точка постоянная , да ну нафик )

А оконную процедуру перемести в класс окна. Тогда можно избавиться от статических переменных

И переходи на MFC! Ага

* MainWindow2.rar (8.97 Кб - загружено 966 раз.)
« Последнее редактирование: 14-08-2010 20:28 от Алексей1153++ » Записан

Topic
Интересующийся

ru
Offline Offline

« Ответ #9 : 16-08-2010 18:41 » 

Алексей, большое спасибо!
Код работает замечательно.

А MFC мне как-то не очень... Планирую осваивать C#.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #10 : 16-08-2010 19:01 » 

А мне C# не очень ) Изучаю Qt ))
Записан

Azlk90
Новенький

ru
Offline Offline

« Ответ #11 : 04-12-2011 10:58 » 

Привет форумчане, у меня с почти такой же программой возникла проблема:
 KWnd.h
Код:


//====================================
//KWnd.h
#pragma once
#include "stdafx.h"
#include<Windows.h>

class Kwnd
{
public:

KWnd(LPCTSTR windowName, HINSTANCE hInst, int cmdShow,
LRESULT (WINAPI* pWndProc)(HWND,UINT,WPARAM,LPARAM),
LPCTSTR menuName = NULL,
int x = CW_USEDEFAULT, int y = 0 ,
int width = CW_USEDEFAULT , int height = 0,
UINT classStyle = CS_HREDRAW | CS_VREDRAW,
DWORD windowStyle = WS_OVERLAPPEDWINDOW,
HWND hParent= NULL);


HWND GetWnd(){ return hWnd;}


private:
protected:
HWND hWnd;
WNDCLASSEX wc;


};



При компиляции выдаёт:
1>d:\project32\sketcher2\win32path1\win32path1\kwnd.h(18): error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию

1>d:\project32\sketcher2\win32path1\win32path1\kwnd.h(18): warning C4183: KWnd: отсутствие возвращаемого типа; предполагается функция-член, возвращающая "int"

не могу понять почему он требует от этого возвратить тип int  А черт его знает...
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #12 : 04-12-2011 15:35 » new

Найди отличия KWnd vs.  Kwnd
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines