| Summary: | Wine разрешает WM декорировать окна, которые декорируются самим приложением | ||
|---|---|---|---|
| Product: | WINE@Etersoft | Reporter: | Анатолий Лютин <vostok> |
| Component: | Окна / фокус / перерисовка | Assignee: | BUGS@Etersoft <bugs> |
| Status: | CLOSED INVALID | QA Contact: | |
| Severity: | minor | ||
| Priority: | P4 | CC: | kondratyuk, lav, olezha |
| Version: | 1.0.9 | ||
| Target Milestone: | --- | ||
| Hardware: | PC | ||
| OS: | All | ||
| Whiteboard: | |||
| Заявки RT: | Связано с: | ||
| Дата напоминания: | |||
| Bug Depends on: | |||
| Bug Blocks: | 1982, 3000 | ||
|
Description
Анатолий Лютин
2008-06-24 17:28:14 MSD
Уточни пожалуйста тему и содержание баги, чтобы было понятно, как это может быть связано с конкретной проблемой (подразумевается, что речь идёт об окнах КМ-Школы). Я до сих пор не смог понять как такая бага может быть организована. Или это нужно исследовать с помощью тестовой программы? Что говорят разработчики КМ-Школы про это? (In reply to comment #1) > Уточни пожалуйста тему и содержание баги, > чтобы было понятно, как это может быть > связано с конкретной проблемой > (подразумевается, что речь идёт об окнах > КМ-Школы). Врубается wine-вское декорирование вместо декора приложения, забиваются кнопки системного меню системным меню декоратора wine. Смотрите багу про "крестик" > Я до сих пор не смог понять как такая бага > может быть организована. Нужно особое заполнение структуры класса окна. > Или это нужно > исследовать с помощью тестовой программы? В принципе можно, но тест будет выдавать результат что всё хорошо, т.к. wine создаст эти кнопки, но они будут забиты декоратором wine (следовательно область системного меню будет принадлижать, допустим, KDE, а из теста невозможно и архитекрутно неверно обратиться/обращаться к нему). > Что говорят разработчики КМ-Школы про это? Они тут причём? Они просто используюст стандартные возможность Delphi. В Delphi очень легко сделать сабклассинг любого приложения. Что такое сабклассинг? Между нами девочками, это слово, которым обычно пугают новичков, добавляя к нему еще умные слова вроде хендл, идентификатор окна, WndProc и т.д. В реальности сабклассинг ? перехват системных сообщений. Вообще вся работа Windows построена на сообщениях. То есть, когда юзер Вася Пупкин щелкает левой кнопкой мыши по иконке в верхнем левом углу окна, Windows говорит окну WM_SYSCOMMAND, батенька, а окно в свою очередь открывает системное меню. Когда окно (не всегда окно :) сабклассят, то перехватывают сообщения от Windows и говорят совсем другое. Например, юзер Вася щелкает левой кнопкой мыши по иконке в верхнем правом углу, Windows говорит WM_SYSCOMMAND, батенькаЋ, а мы, услышав это, затыкаем Windows и говорим WM_QUIT, млин и окно идет гулять, то есть закрывается :). При этом юзер Вася удивляется больше всех :), после него удивляется Windows, и ухмыляется наша программа :). Как это делать? Можно сидеть самому отлавливать системные сообщения, но это отсылает нас, нет не туда, куда ты подумал, а в глубины Win32 API, а в этот подвал мне порой лезть неохота. Для этого дела есть более удобная вещь, написанная, кстати, на Visual Basic, а именно элемент управления Subclass (http://www.softcircuits.com). Статья из http://vbrussian.com/Article.asp?ID=87 А есть информация, какие сообщения нужно перехватить и обработать по-своему, чтобы добиться такого поведения: отключить стандартную декорацию окна и нарисовать свой крестик, посылающий WM_SYSCOMMAND? (In reply to comment #4) > А есть информация, какие сообщения нужно > перехватить и обработать по-своему, > чтобы добиться такого поведения: отключить > стандартную декорацию окна и нарисовать > свой крестик, посылающий WM_SYSCOMMAND? > http://forum.x-coder.ru/showthread.php?p=6715 2.08. Как мне сделать окно нестандаpтной формы, например, как у Norton
CrashGuard, в форме щита?
int SetWindowRgn(
HWND hWnd, // дескриптор окна
HRGN hRgn, // дескриптор региона, созданного вызовами
// CreateEllipticRgn(), CreateRectRgn() или др.
BOOL bRedraw // TRUE, если нужно перерисовать окно после смены
региона
);
Вот пример, делающий окно с закругленными углами:
HRGN myrgn;
myrgn=CreateRoundRectRgn(0,0,Width,Height,20,20);
SetWindowRgn(hWnd, myrgn, TRUE);
Регион ни в коем случае не нужно закрывать с помощью вызова
DeleteObject(...) - это сделает система при необходимости
(после вызова SetWindowRgn()).
А вот пример создания pегиона, по битмапу.
//
// BitmapToRegion: Create a region from the "non-transparent"
// pixels of a bitmap
// Author : Jean-Edouard Lachand-Robert
// (http://www.geocities.com/Paris/LeftBank/1160/resume.htm), June 1998.
//
// hBmp : Source bitmap
// cTransparentColor : Color base for the "transparent" pixels
// (default is black)
// cTolerance : Color tolerance for the "transparent" pixels.
//
// A pixel is assumed to be transparent if the value of each of its 3
// components (blue, green and red) is
// greater or equal to the corresponding value in cTransparentColor and
is
// lower or equal to the corresponding value in cTransparentColor +
// cTolerance.
//
HRGN BitmapToRegion (HBITMAP hBmp,
COLORREF cTransparentColor = 0,
COLORREF cTolerance = 0x101010)
{
HRGN hRgn = NULL;
if (hBmp)
{
// Create a memory DC inside which we will scan the bitmap content
HDC hMemDC = CreateCompatibleDC(NULL);
if (hMemDC)
{
// Get bitmap size
BITMAP bm;
GetObject(hBmp, sizeof(bm), &bm);
// Create a 32 bits depth bitmap and select it into the memory DC
BITMAPINFOHEADER RGB32BITSBITMAPINFO = {
sizeof(BITMAPINFOHEADER), // biSize
bm.bmWidth, // biWidth;
bm.bmHeight, // biHeight;
1, // biPlanes;
32, // biBitCount
BI_RGB, // biCompression;
0, // biSizeImage;
0, // biXPelsPerMeter;
0, // biYPelsPerMeter;
0, // biClrUsed;
0 // biClrImportant;
};
VOID * pbits32;
HBITMAP hbm32 = CreateDIBSection(hMemDC,
(BITMAPINFO*)&RGB32BITSBITMAPINFO,
DIB_RGB_COLORS, &pbits32, NULL, 0);
if (hbm32)
{
HBITMAP holdBmp = (HBITMAP)SelectObject(hMemDC, hbm32);
// Create a DC just to copy the bitmap into the memory DC
HDC hDC = CreateCompatibleDC(hMemDC);
if (hDC)
{
// Get how many bytes per row we have for the bitmap bits
// (rounded up to 32 bits)
BITMAP bm32;
GetObject(hbm32, sizeof(bm32), &bm32);
while (bm32.bmWidthBytes % 4)
bm32.bmWidthBytes++;
// Copy the bitmap into the memory DC
HBITMAP holdBmp = (HBITMAP)SelectObject(hDC, hBmp);
BitBlt(hMemDC, 0, 0, bm.bmWidth, bm.bmHeight,
hDC, 0, 0, SRCCOPY);
// For better performances, we will use the
// ExtCreateRegion() function to create the
// region. This function take a RGNDATA structure on
// entry. We will add rectangles by
// amount of ALLOC_UNIT number in this structure.
#define ALLOC_UNIT 100
DWORD maxRects = ALLOC_UNIT;
HANDLE hData = GlobalAlloc(GMEM_MOVEABLE,
sizeof(RGNDATAHEADER) +
(sizeof(RECT) * maxRects));
RGNDATA *pData = (RGNDATA *)GlobalLock(hData);
pData->rdh.dwSize = sizeof(RGNDATAHEADER);
pData->rdh.iType = RDH_RECTANGLES;
pData->rdh.nCount = pData->rdh.nRgnSize = 0;
SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0);
// Keep on hand highest and lowest values for the
// "transparent" pixels
BYTE lr = GetRValue(cTransparentColor);
BYTE lg = GetGValue(cTransparentColor);
BYTE lb = GetBValue(cTransparentColor);
BYTE hr = min(0xff, lr + GetRValue(cTolerance));
BYTE hg = min(0xff, lg + GetGValue(cTolerance));
BYTE hb = min(0xff, lb + GetBValue(cTolerance));
// Scan each bitmap row from bottom to top (the bitmap is
// inverted vertically)
BYTE *p32 = (BYTE *)bm32.bmBits +
(bm32.bmHeight - 1) * bm32.bmWidthBytes;
for (int y = 0; y < bm.bmHeight; y++)
{
// Scan each bitmap pixel from left to right
for (int x = 0; x < bm.bmWidth; x++)
{
// Search for a continuous range of "non
// transparent pixels"
int x0 = x;
LONG *p = (LONG *)p32 + x;
while (x < bm.bmWidth)
{
BYTE b = GetRValue(*p);
if (b >= lr && b <= hr)
{
b = GetGValue(*p);
if (b >= lg && b <= hg)
{
b = GetBValue(*p);
if (b >= lb && b <= hb)
// This pixel is "transparent"
break;
}
}
p++;
x++;
}
if (x > x0)
{
// Add the pixels (x0, y) to (x, y+1) as a
// new rectangle in the region
if (pData->rdh.nCount >= maxRects)
{
GlobalUnlock(hData);
maxRects += ALLOC_UNIT;
hData = GlobalReAlloc(hData,
sizeof(RGNDATAHEADER) +
(sizeof(RECT) * maxRects),
GMEM_MOVEABLE);
pData = (RGNDATA *)GlobalLock(hData);
}
RECT *pr = (RECT *)&pData->Buffer;
SetRect(&pr[pData->rdh.nCount], x0, y, x, y+1);
if (x0 < pData->rdh.rcBound.left)
pData->rdh.rcBound.left = x0;
if (y < pData->rdh.rcBound.top)
pData->rdh.rcBound.top = y;
if (x > pData->rdh.rcBound.right)
pData->rdh.rcBound.right = x;
if (y+1 > pData->rdh.rcBound.bottom)
pData->rdh.rcBound.bottom = y+1;
pData->rdh.nCount++;
// On Windows98, ExtCreateRegion() may fail if
// the number of rectangles is too
// large (ie: > 4000). Therefore, we have to
// create the region by multiple steps.
if (pData->rdh.nCount == 2000)
{
HRGN h = ExtCreateRegion(NULL,
sizeof(RGNDATAHEADER) +
(sizeof(RECT) * maxRects),
pData);
if (hRgn)
{
CombineRgn(hRgn, hRgn, h, RGN_OR);
DeleteObject(h);
}
else
hRgn = h;
pData->rdh.nCount = 0;
SetRect(&pData->rdh.rcBound,
MAXLONG, MAXLONG, 0, 0);
}
}
}
// Go to next row (remember, the bitmap is
// inverted vertically)
p32 -= bm32.bmWidthBytes;
}
// Create or extend the region with the remaining
// rectangles
HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) +
(sizeof(RECT) * maxRects), pData);
if (hRgn)
{
CombineRgn(hRgn, hRgn, h, RGN_OR);
DeleteObject(h);
}
else
hRgn = h;
// Clean up
GlobalFree(hData);
SelectObject(hDC, holdBmp);
DeleteDC(hDC);
}
DeleteObject(SelectObject(hMemDC, holdBmp));
}
DeleteDC(hMemDC);
}
}
return hRgn;
}
Похоже с документированием этой темы достаточно плохо, раз есть ссылки только на FAQ для новичков и статьи, в которых их автору предлагают почитать что такое сабклассинг :) (In reply to comment #8) > Похоже с документированием этой темы > достаточно плохо, раз есть ссылки только на > FAQ для новичков и статьи, в которых их > автору предлагают почитать что такое > сабклассинг :) > Вовсе нет, просто я подобрал наиболее понятные статьи для тех кто "не в теме". Официальная документация: http://msdn.microsoft.com/en-us/library/bb773183.aspx http://msdn.microsoft.com/en-us/library/aa268967(VS.60).aspx http://msdn.microsoft.com/en-us/library/ms997565.aspx http://msdn.microsoft.com/en-us/library/ms229681.aspx http://msdn.microsoft.com/en-us/library/ms997511.aspx В общем документации навалом. Вообще-то я хотел узнать твои соображения как это могло бы быть сделано, а получил ответ "читайте правила, там всё написано". (In reply to comment #10) > Вообще-то я хотел узнать твои соображения > как это могло бы быть сделано, а получил > ответ "читайте правила, там всё написано". > Читайте комментарий номер 2 сначала. Я ответил: > Я до сих пор не смог понять как такая бага > может быть организована. Нужно особое заполнение структуры класса окна. И собственно надо сделать так, чтобы структура описания окна, которое заполнило приложение, не переписывалась wine-ном. Наверное не так сложно, если покапаться... Больше не поручаем заданий bugs@. Задача по релизу W@E 1.0.9 Уже давно не актуально, закрываю. |