imho.ws
IMHO.WS  

Вернуться   IMHO.WS > Компьютеры > Программирование
Опции темы
Старый 15.09.2004, 17:04     # 1
EjikVTumane
Member
 
Аватар для EjikVTumane
 
Регистрация: 18.04.2002
Адрес: Ф туманах Новосибирска...
Сообщения: 378

EjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собой
Создание непрямоугольного окна с изменяемым размером (WinAPI)

Для получения окна произвольной формы с изменяемым размером обрабатываю WM_SIZE, но при уменьшении размера окна за правой и нижней границей тянется шлейф. Причем только за частями границы, которые отличаются от исходного прямоугольного региона (например за скругленными углами окна).

Самое забавное - есть замечательный пример написанный на MFC http://www.rsdn.ru/article/files/Classes/skindlg.xml и все прекрасно работает. А на WinAPI не получается

Как можно решить данную проблему?

Код:
case WM_SIZE:
{
      RECT clientRect, wndRect;
      GetClientRect(hWnd, &clientRect);
      UpdateMainFrame(((int)(short)LOWORD(lParam)), ((int)(short)HIWORD(lParam)));
      WindowRgn = BitmapToRegion(MainFrame, RGB(255, 0, 255));
      SetWindowRgn(hWnd, WindowRgn, FALSE);
      hdc = GetDC(hWnd);
      HDC MainFrameDC;
      MainFrameDC = CreateCompatibleDC(NULL);
      SelectObject(MainFrameDC, MainFrame);
      BitBlt(hdc, 0, 0, clientRect.right, clientRect.bottom, MainFrameDC, 0, 0, SRCCOPY);
      ReleaseDC(hWnd, hdc);
      DeleteDC(MainFrameDC);

      return 0;
}
Пара пояснений к коду:
UpdateMainFrame - создается BITMAP
BitmapToRegion - создается регион на основе BITMAP'а

Последний раз редактировалось Gunslinger; 15.09.2004 в 17:23.
EjikVTumane вне форума  
Старый 21.09.2004, 14:55     # 2
Teklbery
Guest
 
Сообщения: n/a

Вот попробуй етот код на Дельфяне, если что разберешся

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Timer1: TTimer;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure buttonclick(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure muve(Sender: TObject; Shift: TShiftState; X, Y: Integer);
procedure Timer1Timer(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
kk:byte;
xx,yy,xxl,yyl:integer;
implementation

{$R *.DFM}


procedure TForm1.Button1Click(Sender: TObject);
var hwnd:longint;
rgn:hrgn;
poi:array[1..10] of tpoint;
n,m,l,i,j:integer;
begin m:=5;
poi[1].x:=0;
poi[1].y:=0;
poi[2].x:=0;
poi[2].y:=form1.Height div 2;
poi[3].x:=form1.Width div 2;
poi[3].y:=form1.Height;
poi[4].x:=form1.Width;
poi[4].y:=form1.Height div 2;
poi[5].x:=form1.Width;
poi[5].y:=0;
rgn:=CreatePolygonRgn(poi,m,i);
setwindowrgn(form1.Handle ,rgn,true);
end;

function BitmapToRegion(Bitmap: TBitmap; TransColor: TColor): HRGN;
var X,Y: Integer;
XStart: Integer;
pbByteArray;
begin Result:= 0;
for Y:= 0 to Bitmap.Height - 1 do
begin
X:= 0;
//with bitmap do
pb:=bitmap.ScanLine[y];
while X <Bitmap.Width do
begin
while (X <Bitmap.Width) and (pb^[X] =TransColor) do
inc(X);
if X >=Bitmap.Width then
Break;
XStart := X;
while (X <Bitmap.Width) and (pb^[x]<>TransColor) do
Inc(X);
if Result = 0 then
Result := CreateRectRgn(XStart, Y, X, Y + 1)
else
CombineRgn(Result, Result,CreateRectRgn(XStart, Y, X, Y + 1), RGN_OR);
end;
{with bitmap do
while X <Width do
begin
while (X <Width) and (Canvas.Pixels[X, Y] = TransColor) do
Inc(X);
if X >=Width then
Break;
XStart := X;
while (X <Width) and (Canvas.Pixels[X, Y] <>TransColor) do
Inc(X);
if Result = 0 then
Result := CreateRectRgn(XStart, Y, X, Y + 1)
else
CombineRgn(Result, Result,
CreateRectRgn(XStart, Y, X, Y + 1), RGN_OR);
end;}
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var rgn:hrgn;
Bitmap: TBitmap;
color:TColor;
begin Bitmap := TBitmap.Create;
Bitmap.LoadFromFile('c:\11.bmp');

color:=255;
rgn:=BitmapToRegion(bitmap,color);
setwindowrgn(form1.Handle ,rgn,true);
form1.Canvas.Draw(-3,-24,bitmap);
end;


procedure TForm1.Button3Click(Sender: TObject);
begin
CLOSE
end;

procedure TForm1.buttonclick(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin if ord(button)=0 then if kk=0 then kk:=1
else kk:=0
else kk:=1;
end;

procedure TForm1.muve(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var c:cardinal;
begin if kk=0 then begin
xx:=xx-(xxl-x);
yy:=yy-(yyl-y);
xxl:=x;
yyl:=y;
form1.Caption:=inttostr(xx);
SetWindowPos(form1.handle,form1.handle,xx,yy,form1.Width,form1.Height, c);
timer1.Interval:=100;
end
else form1.Caption:='aaaaaaaaaa';
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var c:cardinal;
begin //SetWindowPos(form1.handle,getnextwindow(form1.handle,1),xx,yy,form1.Wi dth,form1.Height,c);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin kk:=12;
end;

end.
 
Старый 21.09.2004, 18:22     # 3
EjikVTumane
Member
 
Аватар для EjikVTumane
 
Регистрация: 18.04.2002
Адрес: Ф туманах Новосибирска...
Сообщения: 378

EjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собой
thx конечно, но вопрос был не в способе реализации, а с какого перепуга отрисовка на DC'шке приводит к отрисовке последнего пикселя за границами региона (при ресайзе), при этом если уменьшить высоту и ширину на пиксель при BitBlt, то последний пиксель останется не отрисованым (хотя это изначально не вариант, так как с координатами все нормально).
А тут экзампл на дельфях помощник в последнюю очередь.
EjikVTumane вне форума  
Старый 22.09.2004, 10:07     # 4
Teklbery
Guest
 
Сообщения: n/a

В примере конкретно происходит ресайз, и нигде нету лишних пикселей, я даже тебе со вставкой картинок дал пример, для наглядности если у тебя последний пиксель прорисовывается , это у тебя скорее всего обновления не происходит либо скапливается мусор, попробуй очистить его перед тем как делать ресайз, сделай апдейт и потом ресайз.
 
Старый 22.09.2004, 12:37     # 5
EjikVTumane
Member
 
Аватар для EjikVTumane
 
Регистрация: 18.04.2002
Адрес: Ф туманах Новосибирска...
Сообщения: 378

EjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собой
Смотри, переносим код в обработку WM_ERASEBKGND (это к вопросу о том, что обновление не происходит):
Код:
case WM_ERASEBKGND:
{
	GetWindowRect(hWnd, &windowRect);
	UpdateMainFrame(windowRect.right - windowRect.left, windowRect.bottom - windowRect.top);
	frameRegion = BitmapToRegion(MainFrame, RGB(255, 0, 255));
	SetWindowRgn(hWnd, frameRegion, FALSE);
	HBRUSH brush;
	brush = CreatePatternBrush(MainFrame);
	FillRgn(hdc, frameRegion, brush);
	DeleteObject(brush);
	return 0;
}
BITMAP тоже чистится каждый раз перед созданием:
Код:
void UpdateMainFrame(int width, int height)
{
	HDC MainFrameDC;

	if(MainFrame != NULL)
		DeleteObject(MainFrame);
	MainFrame = CreateBitmap(width, height, 1, 32, NULL);
	MainFrameDC = CreateCompatibleDC(NULL);
	SelectObject(MainFrameDC, MainFrame);

	//собираем BITMAP из кусочков
	BitBlt(MainFrameDC, 0, 0, bitmap11info.bmWidth, bitmap11info.bmHeight, bitmap11hdc, 0, 0, SRCCOPY);
	StretchBlt(MainFrameDC, bitmap11info.bmWidth, 0, width-bitmap13info.bmWidth-bitmap11info.bmWidth, bitmap12info.bmHeight,
		bitmap12hdc, 0, 0, bitmap12info.bmWidth, bitmap12info.bmHeight, SRCCOPY);
	BitBlt(MainFrameDC, width-bitmap13info.bmWidth, 0, bitmap13info.bmWidth, bitmap13info.bmHeight, bitmap13hdc, 0, 0, SRCCOPY);

	StretchBlt(MainFrameDC, 0, bitmap11info.bmHeight, bitmap21info.bmWidth, height-bitmap11info.bmHeight-bitmap31info.bmHeight,
		bitmap21hdc, 0, 0, bitmap21info.bmWidth, bitmap21info.bmHeight, SRCCOPY);
	StretchBlt(MainFrameDC, bitmap21info.bmWidth, bitmap11info.bmHeight, width-bitmap23info.bmWidth-bitmap21info.bmWidth, height-bitmap12info.bmHeight-bitmap32info.bmHeight,
		bitmap22hdc, 0, 0, bitmap22info.bmWidth, bitmap22info.bmHeight, SRCCOPY);
	StretchBlt(MainFrameDC, width-bitmap23info.bmWidth, bitmap11info.bmHeight, bitmap23info.bmWidth, height-bitmap11info.bmHeight-bitmap31info.bmHeight,
		bitmap23hdc, 0, 0, bitmap23info.bmWidth, bitmap23info.bmHeight, SRCCOPY);


	BitBlt(MainFrameDC, 0, height-bitmap31info.bmHeight, bitmap31info.bmWidth, bitmap31info.bmHeight, bitmap31hdc, 0, 0, SRCCOPY);
	StretchBlt(MainFrameDC, bitmap31info.bmWidth, height-bitmap32info.bmHeight, width-bitmap33info.bmWidth-bitmap31info.bmWidth, bitmap32info.bmHeight,
		bitmap32hdc, 0, 0, bitmap32info.bmWidth, bitmap32info.bmHeight, SRCCOPY);
	BitBlt(MainFrameDC, width-bitmap33info.bmWidth, height-bitmap33info.bmHeight, bitmap33info.bmWidth, bitmap33info.bmHeight, bitmap33hdc, 0, 0, SRCCOPY);

	DeleteDC(MainFrameDC);
	GetObject(MainFrame, sizeof(MainFrameInfo), &MainFrameInfo);
}
Получаем - при каждой перерисовке устанавливаем окну новый регион, и заполняем его кистью, созданной на основе BITAMP'а. И ежу понятно , что запихивать этот код в обработку WM_ERASEBKGND - это гнусно и ОЧЕНЬ не практично (но для иллюстрации потянет).

Далее смотрим MSDN :
The SetWindowRgn function sets the window region of a window. The window region determines the area within the window where the system permits drawing. The system does not display any portion of a window that lies outside of the window region.

Иными словами говоря - не должно изображение за регион выходить.

А что получается смотри во вложении.
Изображения
Тип файла: gif resize.gif (4.2 Кбайт, 11 просмотров - Кто скачивал? )
EjikVTumane вне форума  
Старый 23.09.2004, 23:57     # 6
Gem Single
Newbie
 
Аватар для Gem Single
 
Регистрация: 21.07.2004
Адрес: Брест
Сообщения: 26

Gem Single Путь к славе только начался
Вот наверное из-за того, что вынес изменение региона в WM_ERASEBKGND, такая фигня и получается... При изменении региона винда рекурсивно вызывает WM_ERASEBKGND ещё раз, тут то всё и происходит.
__________________
Spel chekers, hoo neeeds em?
Gem Single вне форума  
Старый 24.09.2004, 04:12     # 7
EjikVTumane
Member
 
Аватар для EjikVTumane
 
Регистрация: 18.04.2002
Адрес: Ф туманах Новосибирска...
Сообщения: 378

EjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собой
В WM_ERASEBKGND я вынес для примера, этого оно в WM_SIZE было, этот код хоть куда пихай (в тот же WM_NCPAINT) - результат один. Ну и вообще в SetWindowRgn третий параметр FALSE - указывает что перерисовка после изменения региона не требуется. Также, я могу в обработчике WM_ERASEBKGND ничего не перерисовывать, а просто return 0 делать - это не поможет, то бишь дело тут в другом. Ну и как видно на картинке - шлейф то только за частями, отличающимися от первоначального прямоугольного региона, а так был бы за всем окном.
Да к томуже FillRgn делается для того же региона, который установлен как регион окна .
EjikVTumane вне форума  
Старый 24.09.2004, 15:00     # 8
VeryLucky
Guest
 
Сообщения: n/a

http://www.rsdn.ru/article/files/Classes/skindlg.xml
 
Старый 24.09.2004, 16:47     # 9
EjikVTumane
Member
 
Аватар для EjikVTumane
 
Регистрация: 18.04.2002
Адрес: Ф туманах Новосибирска...
Сообщения: 378

EjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собой
VeryLucky
Ну да, а из первого поста не заметно, что про эту статью я в курсе и под MFC все работает?
EjikVTumane вне форума  
Старый 26.09.2004, 00:55     # 10
Gem Single
Newbie
 
Аватар для Gem Single
 
Регистрация: 21.07.2004
Адрес: Брест
Сообщения: 26

Gem Single Путь к славе только начался
Цитата:
Сообщение от Gunslinger
В WM_ERASEBKGND я вынес для примера, этого оно в WM_SIZE было, этот код хоть куда пихай (в тот же WM_NCPAINT) - результат один. Ну и вообще в SetWindowRgn третий параметр FALSE - указывает что перерисовка после изменения региона не требуется. Также, я могу в обработчике WM_ERASEBKGND ничего не перерисовывать, а просто return 0 делать - это не поможет, то бишь дело тут в другом. Ну и как видно на картинке - шлейф то только за частями, отличающимися от первоначального прямоугольного региона, а так был бы за всем окном.
Да к томуже FillRgn делается для того же региона, который установлен как регион окна .
Блин, скачал я тот пример на MFC.
SetWindowRgn там вызывается с bRepaint=TRUE!!! Попробуй...
А ещё там Sleep(0) сразу после SetWindowRgn().
__________________
Spel chekers, hoo neeeds em?

Последний раз редактировалось Gem Single; 26.09.2004 в 00:58.
Gem Single вне форума  
Старый 26.09.2004, 07:54     # 11
EjikVTumane
Member
 
Аватар для EjikVTumane
 
Регистрация: 18.04.2002
Адрес: Ф туманах Новосибирска...
Сообщения: 378

EjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собойEjikVTumane Имеются все основания чтобы гордиться собой
Gem Single
Похоже на правду, посмотрим ...
EjikVTumane вне форума  


Ваши права в разделе
Вы НЕ можете создавать новые темы
Вы не можете отвечать в темах.
Вы НЕ можете прикреплять вложения
Вы НЕ можете редактировать свои сообщения

BB код Вкл.
Смайлы Вкл.
[IMG] код Выкл.
HTML код Выкл.

Быстрый переход


Часовой пояс GMT +4, время: 18:17.




Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.