Что такое код combinergn

HRGN, CombineRgn. Программа работает некоторое время и виснит.

Задача: искать пересечения регионов и подсчитывать их.
В итоге: программа компилится, работает, работает. а потом виснит (своеобразно) При чем время до зависания напрямую зависит от скорости наступления события OnTime Таймера.
Помогите понять что вызывает такой эффект. Я не очень понимаю как устроена структура регионов и может быть я делаю с ними то, чего не стоило бы делать

06.04.2012, 13:29

Программа выключается через некоторое время
Написал программу в vc++, запустил в режиме отладки. А она должна считать, много, иногда несколько.

Компьютер работает некоторое время и перезагружается (синий экран)
Компьютер купил 2 года назад. Недавно стал перезагружаться с синим экраном. Если я сижу в.

комп загружается и работает некоторое время, после чего просто виснет
доброго времени суток! хотелось бы узнать вашего мнения. Проблема в следующем. комп загружается и.

Некоторое время после включения компьютера интернет очень медленно работает
Примерно 20 минут после включения компьютера очень медленно открываются все сайты во всех.

Программа запускается, но через некоторое время выскакивает сообщение о прекращении работы программы.
Доброго дня! За окном мерзкая дождливая погода, в Мире Танков отличная акция, на столе упаковки от.

Что такое код combinergn

We recommend upgrading to the latest Google Chrome or Firefox.

Join GitHub today

GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.

Win32API / libraries / gdi32 / CombineRgn.md

Function name : CombineRgn

The CombineRgn function combines two regions and stores the result in a third region. The two regions are combined according to the specified mode.

hrgnDest [in] Handle to a new region with dimensions defined by combining two other regions. (This region must exist before CombineRgn is called.)

hrgnSrc1 [in] Handle to the first of two regions to be combined.

hrgnSrc2 [in] Handle to the second of two regions to be combined.

fnCombineMode [in] Specifies a mode indicating how the two regions will be combined.

The return value specifies the type of the resulting region. It can be one of the following values.

BMW 3 series Touring ��GrauBlau�� › Бортжурнал › 94. Немного кодирования (DDE, KOMBI, ССС)

Недавно дооснащали круизом X1 DimanSPB . Он об этом вроде бы еще не писал, так что я в каком-то смысле спойлерю =)

Впервые за долгое время взял ноут и шнурок, все не до этого было. Для меня это послужило своеобразным стимулом дойти и до своей машины и закодировать некоторые функции, которые давно хотел прописать себе.

В частности:
— изменить межсервисный интервал на 7000 км;
— активировать ползунок круиз контроля;
— русифицировать таки CCC.

Изменение межсервисного интервала.

Особенно актуальная и полезная фича для дизелистов, вроде меня, меняющих масло каждые 6-8 тык.
Азов кодирования описывать не буду, опишу основные моменты:
1) NCS’ом читаем DDE(43DMO) в .TRC;
2) Затем в NCS Dummy выбираем соответствующий нашему блок и смотрим какие значения в нем предусмотрены для параметра OELWARTUNGSINTERVALL;
3) Вероятнее всего нужного там не окажется (хотя может и быть, у меня нашелся), но это не беда, можно прописать нужный самостоятельно как наказал u36a . Для этого правый клик по OELWARTUNGSINTERVALL и выбираем Add Value;
4) Прописываем новое значение со следующим по порядку номером опции, параметр, отвечающий за величину межсервисного интервала состоит из 4х символов, первые два — пробег, вторые два — интервал в неделях. Сама приборка эти значения округляет и трактует фривольно. Опытным путем подбираем нужные значения.
5)В Module Functions выбираем «Update module»
6) Далее как обычно: подгрузить в Dummy трейс .TRC с DDE, выбрать для него прописанный только что параметр, сохранить в МАН и прошить им DDE.
7) Дать машине «поспать» (можно искусственным путем) и сбросить интервал.
Готово!

Ползунок круиз контроля.

У меня есть круиз, работает он так: при нажатии рычажка коротко на центральном дисплее БК высвечивается заданная скорость.
Сделал тест приборки KI test, номер 2 в сервисном меню комбинашки. Во время теста вокруг спидометра «пляшет» ползунок.

Я просто активировал его, изменив значение параметра SZ_ANSTEUERUNG в блоке Kombi на «aktiv».

Теперь ползунок показывает заданную скорость на круизе. Мелочь, а приятно.

Со второго раза таки удалось русифицировать ССС (пост №71). В первый я чуть не убил голову. В этот раз сделал по сути все тоже самое, только вв этот раз:
— взял другой файл прошивки;
— после прописывания опции $6UD и удаления $851 в FA кодирнул всю машину;
— выполнил сброс всех модулей, в т.ч. MOST’a. «усыпил» машину Rheingold’ом.

Утром меня ждало русское меню. Из разочарований — в меню телефона русские символы так и отображаются кракозябрами (?).

Попутно проштудировал сверху до низу блоки Kombi, DDE и FRM на предмет доступных для кодирования и интересных опций, думаю позже запилю описание интересных опций в этих блоках.

CombineRgn Function

Declare Function CombineRgn Lib «gdi32.dll» (ByVal hDestRgn As Long, ByVal hSrcRgn1 As Long, ByVal hSrcRgn2 As Long, ByVal nCombineMode As Long) As Long

Platforms

  • Windows 95: Supported.
  • Windows 98: Supported.
  • Windows NT: Requires Windows NT 3.1 or later.
  • Windows 2000: Supported.
  • Windows CE: Requires Windows CE 1.0 or later.

Description & Usage

CombineRgn combines two regions to form a third region. The two regions can be combined using a variety of logical operators. Note that the region that receives the combined regions must already be a region — the function cannot create a new one but can change an existing one.

Return Value

The function returns one of the following flags specifying the result of the region combination operation: ERROR An error occured while trying to combine the regions. NULLREGION The combined region is empty, i.e., null. SIMPLEREGION The combined region forms a rectangle. COMPLEXREGION The combined region is not empty but is also not a rectangle.

Visual Basic-Specific Issues


Parameters

hDestRgn A handle to the region to be set to the combination of the two source regions. This region must already have been created, although its contents when passed to the function is irrelevant. hSrcRgn1 The first of the two source regions. hSrcRgn2 The second of the two source regions. nCombineMode One of the following flags specifying the logical operation to use to combine the two regions: RGN_AND The combined region is the overlapping area of the two source regions. RGN_OR The combined region is all the area contained in either of the two source regions, including any overlap. RGN_XOR The combined region is all of the area contained in either of the two source regions, excluding any overlap. RGN_DIFF The combined region is all the area of the first source region except for the portion also included in the second source region. RGN_COPY The combined region is identical to the first source region. The second source region is ignored.

Что такое код combinergn

Windows API предоставляет набор функций, позволяющих описать произвольную (при желании — достаточно сложную) геометрическую фигуру, которая потом может использоваться при работе с окнами, или, в терминологии Delphi, элементами управления. Использование может заключаться, например, в отрисовке на холсте, в задании специфического региона обновления окна, и т.д. Помимо таких вот относительно невинных возможностей, технология регионов позволяяет также глумиться над благородными очертаниями любого потомка TWinControl (иными словами, любым контролом, имеющим Handle, aka TForm, TButton, и т.д.). Особенно широко регионы используются в формах, при их отрисовке и обновлении. Итак, для начала, давайте разберёмся, что такое этот самый регион.

Win32 SDK регион определяет следующим образом:

(имеется в виду, что есть стандартная функция, определяющая входит ли точка (X,Y) в наш регион).

В SDK упомянуты три основных типа регионов: прямоугольные, эллиптические, и полигональные. О чётвёртом типе, прямоугольном с закруглёнными краями, стыдливо умалчивается, ну да и фиг с ним. Видимо это связано с тем, что его можно получить из первых двух. Дело в том, что регионы могут комбинироваться между собой с применением логических операций OR, XOR и т.д. Но к этому мы вернёмся позже.

С точки зрения Windows, регион является обыкновенным объектом GDI, задаваемым дескриптором HRGN. В Delphi также доступен этот тип, и объявление его выглядит следующим образом:

Как видим, ничего сверхъестественного. По сути это указатель на некую структуру в памяти. Структура эта описана следующим образом:

_RGNDATA = record
rdh : TRgnDataHeader ;
Buffer : array [ 0 .. 0 ] of CHAR ;
Reserved : array [ 0 .. 2 ] of CHAR ;
end ;

Что примечательно, в Win32 SDK _RGNDATA объявлена немного иначе. Наиболее любопытный член этой записи, безусловно, TRgnDataHeader. В модуле Windows.pas фигурирует и он:

_RGNDATAHEADER = packed record
dwSize : DWORD ;
iType : DWORD ;
nCount : DWORD ;
nRgnSize : DWORD ;
rcBound : TRect ;
end ;

Вот его стоит рассмотреть подробнее.

dwSize Указывает размер заголовка (т.е. _RGNDATAHEADER) в байтах;
iType Тип региона, всегда равен RDH_RECTANGLES = 1;
nCount Кол-во прямоугольников, из которых составлен регион;
nRgnSize Размер буфера, необходимого для получения структуры TRect, указывающей координаты прямоугольников, составляющих регион. Если размер неизвестен, поле может быть равно нулю;
rcBound Координаты прямоугольника, в который вписан регион.

Вот именно эта структура и задаёт регион, как таковой, и именно с ней работают практически все функции API. Пора познакомиться с ними поближе.
Условно все эти функции можно разбить на три группы: создание/удаление, отрисовка и прочие. Расмотрим их все по порядку. Для удобства я буду приводить не си-шные декларации из SDK, а паскалевские декларации, объявленные в модуле Windows, ибо именно с ними нам и предстоит работать.

Функция Синтаксис Описание
CombineRgn function CombineRgn (p1, p2, p3: HRGN; p4: Integer): Integer; stdcall; Создаёт новый регион p1, комбинируя регионы p2 и p3 на основе режима p4
CreateEllipticRgn function CreateEllipticRgn (p1, p2, p3, p4: Integer): HRGN; stdcall; Создаёт эллиптический регион по четырём координатам
CreateEllipticRgnIndirect function CreateEllipticRgnIndirect (const p1:TRect): HRGN; stdcall; Создаёт эллиптический регион, впсанный в заданный прямоугольник p1
CreatePolygonRgn function CreatePolygonRgn (const Points; Count, FillMode: Integer): HRGN; stdcall; Создаёт полигональный регион по массиву точек Points с числом вершин Count с режимом заливки FillMode
CreatePolyPolygonRgn function CreatePolyPolygonRgn (const pPtStructs; const pIntArray; p3, p4: Integer): HRGN; stdcall; Создаёт регион, состоящий из серии полигонов, задаваемых массивом точек pPtStructs, число вершин каждого из которых указывается в массиве pIntArray с общим числом вершин p3 и режимом заливки p4
CreateRectRgn function CreateRectRgn (p1, p2, p3, p4: Integer): HRGN; stdcall; Создаёт прямоугольный регион по четырём координатам
CreateRectRgnIndirect function CreateRectRgnIndirect (const p1: TRect): HRGN; stdcall; Создаёт прямоугольный регион по заданному прямоугольнику p1
CreateRoundRectRgn function CreateRoundRectRgn (p1, p2, p3, p4, p5, p6: Integer): HRGN; stdcall; Создаёт прямоугольный регион по координатам p1-p4 с эллиптически закруглёнными краями с высотой эллипса скругления p5 и шириной p6
ExtCreateRegion function ExtCreateRegion (XForm: PXForm; Count: DWORD; const RgnData: TRgnData): HRGN; stdcall; Создаёт регион по его данным RgnData размером Count с указанной трансформацией XForm
DeleteObject function DeleteObject (p1: HGDIOBJ): BOOL; stdcall; Удаляет регион и освобождает все, занятые под него ресурсы

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

Функция Синтаксис Описание
SetPolyFillMode function SetPolyFillMode (DC: HDC; PolyFillMode: Integer): Integer; stdcall; Устанавливает режим заливки регионов PolyFillMode для контекста dc
GetPolyFillMode function GetPolyFillMode (DC: HDC): Integer; stdcall; Возвращает текущий режим заливки регионов на конктексте dc
PaintRgn function PaintRgn (DC: HDC; RGN: HRGN): BOOL; stdcall; Рисует регион rgn на контексте dc текущей кистью контекста
FillRgn function FillRgn (DC: HDC; hrgn: HRGN; hbr: HBRUSH): BOOL; stdcall; Заливает регион hrgn на контексте dc с заданной кистью hbr
FrameRgn function FrameRgn (DC: HDC; hrgn: HRGN; hbr: HBRUSH; Width, Height: Integer): BOOL; stdcall; Рисует на контексте dc рамку вокруг региона hrgn кистью hbr соответствующей ширины и высоты Width и Height
Функция Синтаксис Описание
EqualRgn function EqualRgn (p1, p2: HRGN): BOOL; stdcall; Проверяет, являются ли размеры и форма регионов p1 и p2 идентичными
InvertRgn function InvertRgn (DC: HDC; p2: HRGN): BOOL; stdcall; Инвертирует цвета региона p2 на контексте dc
OffsetRgn function OffsetRgn (RGN: HRGN; XOffset, YOffset: Integer): Integer; stdcall; Сдвигает регион rgn по осям X и Y на XOffset и YOffset соответственно
SetRectRgn function SetRectRgn (Rgn: HRgn; X1, Y1, X2, Y2: Integer): BOOL; stdcall; Конвертирует регион rgn в прямоугольный, заданный четырьмя координатами
GetRgnBox function GetRgnBox (RGN: HRGN; var p2: TRect): Integer; stdcall; Возвращает прямоугольник p2, в который вписан указанный регион rgn
RectInRegion function RectInRegion (RGN: HRGN; const Rect: TRect): BOOL; stdcall; Определяет, «влазит» ли пряпоугольник Rect в границы региона rgn
PtInRegion function PtInRegion (RGN: HRGN; X, Y: Integer): BOOL; stdcall; Определяет, входит ли точка (X,Y) в регион rgn
GetRegionData function GetRegionData (RGN: HRGN; p2: DWORD; p3: PRgnData): DWORD; stdcall; Заполняет данными региона rgn буфер PRgnData размером p2, при pRgnData = nil — возвращает размер региона в памяти.

Каким же образом это безобидное и абстрактное, в общем-то, понятие взаимодействует со вполне реальными элементами управления? Ведь все перечисленные функции служат, по большому счёту, для того, чтобы создать некую замысловатую фигуру и тем или другим способом отрисовать её в чьём-то контексте, DC, а о том, чтобы каким-то образом изменить форму той же кнопки и речи даже нет. Дело здесь в том, что мы пока мельком рассмотрели функции, касающиеся создания и манипуляций регионами. А ещё существуют функции работы с окнами, и вот там-то нам все наши созданные регионы и пригодятся. Поглядим, что это за функции.

Функция Синтаксис Описание
SetWindowRgn function SetWindowRgn(hWnd: HWND; hRgn: HRGN; bRedraw: BOOL): Integer; stdcall; Устанавливает для окна с дескриптором hWnd регион отображения hRgn, при взведённом флаге bRedraw — перерисовывая окно
GetWindowRgn function GetWindowRgn(hWnd: HWND; hRgn: HRGN): Integer; stdcall; Возвращает регион отображения hRgn для окна с дескриптором hWnd

Сразу оговорюсь, что на самом деле этих функций гораздо больше, равно как и область применения регионов гораздо ширше. Но нас они пока не волнуют. Итак, мы знаем, как создать и модифицировать регион, как скормить его окну (ибо параметр hWnd есть не что иное, как WinControl.Handle), и как его уничтожить. Настало время слегка поэксперементировать.

Запускаем среду, заводим новый проект, тщательно сохраняем куда попало. В обработчике OnCreate пишем первое, что, по идее, приходит в голову:

Результатом запуска окажется симпатичный эллипс на экране. А теперь попробуйте дописать такой простенький обработчик на OnKeyPress:

В момент выполнения программы при нажатии «p» мы,
по идее должны получить картинку нашей формы. Но как это ни покажется странным, мы получим картинку полной, т.е. неусечённой формы. Собственно, если взглянуть на реализацию GetFormImage — ничего странного не обнаружиться, создаётся виртуальный битмап, на который себя отрисовывает форма и все контролы на ней. Но об этой забавной фиче стоит помнить: для любой, самой извратной формы всегда можно получить её первоначальную картинку функцией GetFormBitmap, а любой загруглённый/продырявленный/звездообразный контрол всегда можно отрисовать на любой левый канвас в его первозданном виде функцией PaintTo.

Аналогичным образом создаются и другие типы регионов, единственное внимание стоит, пожалуй, уделить полигональным. Начнём с самого простого. В делкарации функции есть интересный параметр: FillMode. Согласно SDK он может принимать два значения — ALTERNATE и WINDING. Со вторым всё просто — вычисляются границы, и всё, что между — заливается текущей кистью. А вот первый при заливке анализирует, по какую сторону ребра (чётную или нечётную) он находится. Что это означает, мы увидим на следующем примере.

Запустите программу, посмотрите на результат (она превратит форму в звезду), и поменяйте значение параметра FillMode на ALTERNATE. И запустите её снова. На тот случай, если по каким-то причинам вам влом напрягаться со всякими там модами, ниже приведёны примеры того, что вы могли увидеть:

FillMode = WINDING FillMode = ALTERNATE

Обратите внимание, что если вы кликаете мышкой на «дырку», сообщение получает окно, лежащее под вашей формой. Если форма выведена на пустом десктопе, вы вполне успешно можете из «дырки» вызвать контекстное меню экрана. Т.е. это дейтсвительно «дыра», а не просто прозрачная отрисовка. Теперь разберёмся, как работает функция CreatePolyPolygonRgn. Её предназначение в том, чтобы рисовать сразу несколько регионов, которые могу даже не пересекаться. А могу — и пересекаться, именно для этого и нужен параметр FillMode. Поглядим, как это выглядит, и что оно делает:

Важно помнить, что первый параметр, вновь создаваемый регион, должен существовать до вызова функции.
Из первой серии функций осталось только разобраться с комбинированием регионов, о чем и пойдёт речь далее.

Результат комбинирования определяется четвёртым параметром функции CombineRgn. Давайте посмтрим, какие значения он может принимать.

RGN_ADD Пересечение двух регионов p2 и p3
RGN_COPY Создаёт копию региона p2
RGN_DIFF Вернёт часть p2, не являющуюся частью p3
RGN_OR Объединение двух регионов p2 и p3
RGN_XOR Объединяет регионы p2 и p3, исключая пересекающиеся области

Возвращаемые значения могут быть NULLREGION (пустой регион), SIMPLEREGION (один прямоугольник), COMPLEXREGION (всё остальное) и ERROR (нифига не создано). Посмотрим, как это выглядит на практике (чтобы не сильно мучитья, я просто дописывал предыдущий пример).

Нерасмотренной из первой группы функций осталась только ExtCreateRgn. Я сейчас не буду на ней заостряться, скажу только, что на пару с функцией GetRegionData, она может пригодиться, например, для сохранения и загрузки регионов в файл / из файла.

Регионы нужны не только для того, чтобы резать дырки в формах. Иногда они могут оказаться довольно полезным инструментом именно в своём «родном» качестве, т.е. для отрисовки на экране достаточно сложных геометрических фигур. Например, для вывода карт, представляющих собой совокупность ломанных линий, построенных по массивам точек. Создать такую линию нам уже не составит труда, пора разобраться, как её показать юзеру.

Из функций отрисовки две первые нам уже смутно знакомы: они делают тоже, что делает параметр FillMode (ALTERNATE/WINDING) для функций CreatePolygonRgn и CreatePolyPolygonRgn. GetPolyFillMode получает заданный для указанного контекста режим заливки, а SetPolyFillMode устанавливает его. Просто на этот раз речь идёт не о создании региона, а всего лишь о его отрисовке. Установленное значение будет иметь смысл для всех функций, заливающих регион, т.е. PaintRgn и FillRgn, при этом сам регион останется таким, каким он и был создан, а вот раскрашен будет по разному, в том случае, если он состоит из нескольких пересекающихся регионов. Для простых регионов типа прямоугольника или элипса установка данного значения ничего не меняет.

Итак. Давайте срочно что-нить создадим и нарисуем. Можно, конечно, сделать это в одной функции, например в OnCreate, но тогда изображение будет весьма недолговечным — до первой перерисовки формы. Поэтому поступим иначе: объявим private property fRgn, в OnCreate его инициализируем, в OnPaint будем его отображать, а в OnDestroy — уничтожим. Код методов представлен ниже:

procedure TForm1 . FormCreate ( Sender : TObject ) ;
begin
fRgn : = CreateEllipticRgn ( 10 , 10 , 200 , 200 ) ;
end ;

procedure TForm1 . FormDestroy ( Sender : TObject ) ;
begin
DeleteObject ( fRgn ) ;
end ;

procedure TForm1 . FormPaint ( Sender : TObject ) ;
begin
Canvas . Brush . Color : = clBlack ;
PaintRgn ( Canvas . Handle , fRgn ) ;
end ;

Следует помнить, что Функции отрисовки регионов всегда работают с цветом,
указанным в Canvas.Brush.Color. Даже рисуя бордюр (frame) использоваться будет не цвет Canvas.Pen, что, в общем-то, представляется более логичным, а цвет Canvas.Brush.

Ничего такой получился кружочек. Погребального вида. Давайте сделаем его более жизнерадостным, и заодно разберёмся, как работает FrameRgn:

У меня получилась такая вот картинка:

Насколько я могу судить, функции FillRgn и PaintRgn отличаются друг от друга только тем, что первая позволяет указать дескриптор кисти, не связанной с текущим canvas’ом. Сомнительная фича с точки зрения дельфей, т.к. манипулировать с текущим цветом кисти канваса всяко легче, чем создавать отдельный экземпляр класса TBrush. Вот, собственно, и всё об отрисовке. Примечательно то, что для того, чтобы нарисовать регион нам не нужно знать, что он из себя представляет. Мы просто передаём дескриптор одной и той же процедуре, а она отобразит на экране круг, овал, треугольник, звезду Давида — всё, что угодно.
Функции, представленные в разделе прочее ничего особенно интересного из себя не представляют, и, в общем-то, интуитивно понятны. поэтому рассотрим лишь некоторые из них.

Сделаем это на примере. Давайте озадачимся возможностью таскать мышкой по всей форме круг, созданный в предыдущем примере. Что нам нужно. Во-первых, запоминать, где началось перетаскивание (fStartX, fStartY). Во-вторых, флаг (fDragging), указывающий, что юзер действительно перетскивает наш регион, а не просто гоняет с экрана мух. В третьих, надо узнать, ткнул ли он на регион, а не мимо (PtInRegion). В четвёртых, надо двигать регион по мере того, как он двигает мышь (OffsetRgn). Вот, пожалуй, и всё. На этот раз текст модуля приведу полностью. Единственное что там стоит упомянуть — это свойство DoubleBuffered. Оно выставлено в TRUE, т.к. иначе появляется мерцание. Итак.

uses
Windows , Messages , SysUtils , Variants , >, Graphics ,
Controls , Forms , Dialogs ;

type
TForm1 = class ( TForm )
procedure FormCreate ( Sender : TObject ) ;
procedure FormDestroy ( Sender : TObject ) ;
procedure FormPaint ( Sender : TObject ) ;
procedure FormMouseDown ( Sender : TObject ; Button : TMouseButton ; Shift :
TShiftState ; X , Y : Integer ) ;
procedure FormMouseMove ( Sender : TObject ; Shift :
TShiftState ; X , Y : Integer ) ;
private
< Private declarations >
fDragging : boolean ;
fRgn : hRGN ;
fStartX ,
fStartY : integer ;
public
< Public declarations >
end ;

var
Form1 : TForm1 ;

procedure TForm1 . FormCreate ( Sender : TObject ) ;
begin
fRgn : = CreateEllipticRgn ( 10 , 10 , 200 , 200 ) ;
fDragging : = FALSE ;
DoubleBuffered : = TRUE ;
end ;

procedure TForm1 . FormDestroy ( Sender : TObject ) ;
begin
DeleteObject ( fRgn ) ;
end ;

procedure TForm1 . FormPaint ( Sender : TObject ) ;
var
bmp : TBitmap ;
begin
bmp : = TBitmap . Create ;
try
bmp . LoadFromFile ( ‘C:WINDOWS\Голубые кружева 16.bmp’ ) ;
Canvas . Brush . Bitmap : = bmp ;
PaintRgn ( Canvas . Handle , fRgn ) ;
Canvas . Brush . Color : = clBlack ;
FrameRgn ( Canvas . Handle , fRgn , Canvas . Brush . Handle , 2 , 2 ) ;
finally
Canvas . Brush . Bitmap : = nil ;
bmp . Free ;
end ;
end ;

procedure TForm1 . FormMouseDown ( Sender : TObject ; Button :
TMouseButton ; Shift : TShiftState ; X , Y : Integer ) ;
begin
if ( Button = mbLeft ) and ( PtInRegion ( fRgn , X , Y ) ) then begin
fDragging : = TRUE ;
fStartX : = X ;
fStartY : = Y ;
end ;
end ;

procedure TForm1 . FormMouseMove ( Sender : TObject ; Shift :
TShiftState ; X , Y : Integer ) ;
begin
if ( ssLeft in Shift ) and fDragging then begin
OffsetRgn ( fRgn , X — fStartX , Y — fStartY ) ;
fStartX : = X ;
fStartY : = Y ;
Refresh ;
end ;
end ;

procedure TForm1 . FormMouseUp ( Sender : TObject ; Button : TMouseButton ;
Shift : TShiftState ; X , Y : Integer ) ;
begin
fDragging : = FALSE ;
end ;

Как видим, абсолютно ничего сложного в работе с регионами нет. А вот возможности они дают довольно интересные. Фигуру любой формы можно раскрасить как угодно (в т.ч. и битмапом), вывести на экран, определить, входит ли точка (X,Y) в эту фигуру, двигать её, и многое ещё другое. Для полноты картины нам осталось только научиться сохранять регионы на диск и считывать обратно.

Как уже говорилось в самом начале, все данные о регионе храняться в структуре RGNDATA. Упоминалась также и функция, позволяющая эту структуру получить: GetRegionData. У этой функции есть приятная особенность: если в третий параметр передать nil, то она вернёт размер памяти, необходимый для сохранения региона.

Аналогичным образом можно и прочитать записанный на диск регион:

Функция CombineRgn

Описание:

function CombineRgn(DestRgn, SrcRgn1, SrcRgn2: HRgn; CombineMode: Integer): Integer;

Объединяет области SrcRgn1 и SrcRgn2 и помещает pезультат в DestRgn. CombineMode опpеделяет метод объединения областей.

Параметры:

DestRgn: Область, замещаемая новой областью.
SrcRgn1: Существующая область.
SrcRgn2: Существующая область.
CombineMode: Одна из констант rgn_And, rgn_Copy, rgn_Diff, rgn_Or, rgn_Xor. См. pаздел «Флаги объединения областей, rgn_» в главе 1.

Возвpащаемое значение:

Одна из констант ComplexRegion, Error, NullRegion, SimpleRegion. См. pаздел «Флаги областей» в главе 1.

Белый фликер после функции CombineRgn

Кажется, мерцание генерируется функцией CombineRgn, но я действительно не знаю, почему это происходит, поскольку я никогда не использовал регионы, что, возможно, не хватало некоторых знаний по этому вопросу.

Некоторые события в программе запускают добавление маленьких прямоугольников в основную область, здесь код, который обрабатывает это:

«Белый мерцание» появляется только после аннулирования, если новые регионы объединены с основным.

Здесь, как я реализую двойную буферизацию в WM_PAINT:

УКАЗЫВАЙТЕ, что при создании я включаю размытие DWM за функцией с недопустимым регионом (отличным от основного), что означает, что все, написанное BLACK_BRUSH, приведет к 100% -ной «невидимой» части программы

WM_ERASEBKGND, очевидно, возвращает TRUE без дальнейшей обработки, экземпляр WNDCLASSEX окна имеет значение по умолчанию BLACK_BRUSH как поле hbrBackground.

Я также пытался перехватить и вернуть TRUE из сообщения WM_NCPAINT.

Я делаю все необходимое, чтобы избежать промежуточных разворотов, все, что обрабатывается внутри WM_PAINT, использует backbuffer, также я бы хотел упомянуть, что я не работаю с изображениями/растровыми изображениями. Все рисуется с помощью gdi/gdi+, и ни в каком месте я не выдаю «белый» перерисовку, которая может вызвать упомянутое мерцание. Я немного потерял здесь

Это что-то, что я, возможно, не хватает? Я не могу понять, что может вызвать белый мерцание в этом сценарии

Что такое код combinergn

Вопрос такой: я знаю, что существуют функции создания и управления регионами,
но как их применять, честно говоря, не очень себе представляю. Как с ними работать?
Как создавать регионы и объединять их? Если не сложно, с примерами, плиз.

А нужно мне вот что: взять произвольную BMP-шку и создать окно, имеющее форму этой
BMP-шки (наподобие Автозапуска на CHIP-CD). Буду оч-ч-ень благодарен за примеры.

Здесь, насколько мне известно, применяется такая тактика:
1) Создается прямоугольный регион (под размер рисунка).
Функция CreateRectRgn.
2) В цикле ищутся горизонтальные линии (прозрачного цвета)толщиной в 1 пиксель и создаются прямоугольные регионы под размер этих областей.
3) При помощи CombineRgn с параметром RGN_DIFF «вычитаем» из 1-го региона второй (из общего — тоненький)
4) Вызываем SetWindowRgn.
5) Балдеем! :-)

Про регион из BMP — есть статья Антона Григорьева на «Королевстве Delphi» (www.delphikingdom.com)

Я пишу примерно так:

var
Rgn, Rgn1, Rgn2: HRGN;

Rgn1 := CreateRectRgn(50,50,100,100);
Rgn2 := CreateEllipticRgn(100,100,150,100);
CombineRgn(Rgn, Rgn1, Rgn2, RGN_OR);
SetWindowRgn(Form1.Handle, Rgn, True);

Но не работает! Выводит простую форму. В чем проблема?

Проект-пример Cunnings.zip
(CreateXXXRgn, CombineRgn, SetWindowRgn и еще кое-что)

Вот функции создания и десоздания регионов:

procedure CropWindow( Handle: HWnd; Picture : TPicture );
var
hrgn, hrgn1 : integer;
hdc : integer;
x, y : integer;
Color : TColor;
begin
// Color := Picture.Bitmap.Canvas.Pixels[ 0, 0 ];
Color := clWhite;
hdc := GetDC( Handle );
hrgn := CreateRectRgn( 0, 0, Picture.Graphic.Width, Picture.Graphic.Height );
for x := 1 to Picture.Graphic.Width do
for y := 1 to Picture.Graphic.Height do
if Picture.Bitmap.Canvas.Pixels[ x — 1, y — 1 ] = Color then begin
hrgn1 := CreateRectRgn( x — 1, y — 1, x, y);
CombineRgn( hrgn, hrgn, hrgn1, RGN_DIFF );
DeleteObject( hrgn1 );
end;
SetWindowRgn( Handle, hrgn, true );
//DeleteObject( hrgn );
ReleaseDC( Handle, hdc);
end;

Как раз с BMP»шкой.

>Cosmic © (22.01.03 22:40)
Ошибка в том, что приемный регион в CombineRgn уже должен быть создан! Можно использовать один из исходных или создать еще один

Отлично, спасибо. Еще вопрос: при перехвате WM_NCLBUTTONDOWN (то есть, если я хочу, чтобы форма двигалась, когда я ее хватаю мышкой за любое место) перемещается не регион, который мной создан, а весь контур формы. Можно ли этого избежать?

вероятно, если PtInRegion, то не вызывать унаследованный обработчик

Это как? В смысле, как «не вызывать»?

ВИДЕОКУРС
выпущен 4 ноября!

Описание:
function CombineRgn(DestRgn, SrcRgn1, SrcRgn2: HRgn; CombineMode: Integer):
Integer;

Объединяет области SrcRgn1 и SrcRgn2 и помещает pезультат в DestRgn. CombineMode
опpеделяет метод объединения областей.

Паpаметpы:
DestRgn: Область, замещаемая новой областью.
SrcRgn1: Существующая область.
SrcRgn2: Существующая область.
CombineMode: Одна из констант rgn_And, rgn_Copy, rgn_Diff, rgn_Or, rgn_Xor. См.
pаздел «Флаги объединения областей, rgn_» в главе 1.

Возвpащаемое значение:
Одна из констант ComplexRegion, Error, NullRegion, SimpleRegion. См. pаздел
«Флаги областей» в главе 1.

CombineRgn

WinApi функция CombineRgn.

Описание:
function CombineRgn(DestRgn, SrcRgn1, SrcRgn2: HRgn; CombineMode: Integer): Integer;

Объединяет области SrcRgn1 и SrcRgn2 и помещает pезультат в DestRgn. CombineMode опpеделяет метод объединения областей.

Паpаметpы:
DestRgn: Область, замещаемая новой областью.
SrcRgn1: Существующая область.
SrcRgn2: Существующая область.
CombineMode: Одна из констант rgn_And, rgn_Copy, rgn_Diff, rgn_Or, rgn_Xor. См. «Флаги объединения областей, rgn_».

Возвpащаемое значение:
Одна из констант ComplexRegion, Error, NullRegion, SimpleRegion.

Материал взят из:
Русская спpавка по Windows API

Илон Маск рекомендует:  Как в Word добавить шрифт
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL