procedure ShadeIt(f: TForm; c: TControl; Width: Integer; Color: TColor);
var rect: TRect; old: TColor; begin if (c.Visible) then begin rect := c.BoundsRect; rect.Left := rect.Left + Width;
rect.Top := rect.Top + Width;
rect.Right := rect.Right + Width;
rect.Bottom := rect.Bottom + Width;
old := f.Canvas.Brush.Color; f.Canvas.Brush.Color := Color;
f.Canvas.fillrect(rect); f.Canvas.Brush.Color := old;
end; end;
procedure TForm1.FormPaint(Sender: TObject);
var i: Integer; begin for i := 0to Self.ControlCount - 1do ShadeIt(Self, Self.Controls[i], 3, clBlack);
end;
Взято с
сайта http://www.swissdelphicenter.ch/en/tipsindex.php
Обратится к компоненту по имени можно например так, если стоит 10 CheckBox - от
CheckBox1 до CheckBox10 то For i:=1to10do (FindComponent(Format('CheckBox%d',[i])) as TCheckBox).checked:=true;
Если например эти 10 CheckBox все время используются для групповых операций,
чтобы не перебирать компоненты можно сделать так.
1) Берем ставим на
форму 10 CheckBox 2) объявляем массив
var arr:array[1..10] of TCheckBox
3) Далее присваиваем указатели массиву:
For i:=1to10do arr[i]:=FindComponent(Format('CheckBox%d',[i])) as TCheckBox;
Все,
теперь к каждому CheckBox можно обратится как к элементу массива:
arr[5].checked:=true; Так
как здесь массив статический никаких действий по освобождению памяти делать не
надо, по уничтожении компонентов деструктором формы элементы массива будут
показывать вникуда. В любом случае этот массив занимает в памяти 40 байт - не
большая плата за скорость и удобство.
procedure TForm1.ComboBox1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState); begin if key=vk_F4 then key:=0; end;
Автор
ответа:Vit
Взято с
Vingrad.ru http://forum.vingrad.ru
Следующий пример демонстрирует перехват сообщения CM_DIALOGCHAR на уровне формы.
Это даст нам возможность реагировать на диалоговые комбинации клавишь только,
если нажата клавиша Alt, не давая тем самым отработать стандартному обработчику.
type TForm1 = class(TForm)
Button1: TButton; StringGrid1: TStringGrid; procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure StringGrid1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState); private { Private declarations } procedure CMDialogChar(varMessage: TCMDialogChar);
message CM_DIALOGCHAR;
public { Public declarations } end;
var Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
begin Button1.Caption := 'E&xit'; end;
procedure TForm1.Button1Click(Sender: TObject);
begin Application.Terminate; end;
procedure TForm1.StringGrid1KeyDown(Sender: TObject;
var Key: Word; Shift: TShiftState);
begin ShowMessage('Grid keypress = ' + Char(Key));
Key := 0; end;
procedure TForm1.CMDialogChar(varMessage: TCMDialogChar);
begin if ssAlt in KeyDataToShiftState(Message.KeyData) then inherited; end;
Взято с
Исходников.ru http://www.sources.ru/delphi_src1.shtml
Эта статья взята мной из рассылки "СообЧА. Программирование на Delphi". К
сожалению авторство не указано, но думаю многим будет интересно.
Класс TApplication, являющийся наследником класса TComponent,
представляет собой фундаметальный класс, свойства и методы которого описывают
основные характеристики Windows-приложения. Этот класс активно используется для
выполнения специфических действий, зависящих от операционной системы.
Иерархия TObject – TPersistent – TComponent Модуль Forms В каждом
приложении автоматически создается объект Application типа TApplication –
приложение. Application имеет ряд свойств, методов, событий, характеризующих
приложение в целом. Собственные свойства класса TApplication.
property Active: Boolean;
Свойство возвращает значение true,
если текущее приложение активно. При переходе к другому приложению или при
завершении работы, свойство получает значение false. (Ro)
property
AllowTesting: Boolean;
Свойство представляет информацию для IDE и может
использоваться только самим приложением.
property BiDiKeyboard: string;
Свойство содержит название раскладки клавиатуры, используемой в
ближневосточных языках.
property BiDiMode: TBiDiMode;
Свойство
содержит указание на место размещения приложения при его выполнении в
ближневосточных версиях Windows.
property CurrentHelpFile: string;
Свойство содержит имя текущего файла помощи, имеющего расширение .hlp.
(Ro)
property : DialogHandle: HWnd;
Свойство обеспечивает доступ
к механизму создания окон диалога, не использующих библиотеку VCL. Это свойство
содержит дескриптор окна диалога, созваемого с помощью функции API CreateDialog.
property ExeName: string;
Свойство содержит полное имя файла, в
котором находится программа, и полный путь к ней.
property Handle: HWnd;
Свойство содержит дескриптор программы, который используется
операционной системой Windows.
property HelpFile: string;
Свойство содержит имя справочного файла, который используется по
умолчанию, например, при отсутствии всей информации о справочном файле,
указанном в свойстве CurrentHelpFile.
property Hint: string;
Свойство содержит строковое выражение, определяющее текст всплывающей
подсказки.
property HintColor: TColor;
Свойство содержит
значение цвета всплывающей подсказки.
property HintHidePause: integer;
Свойство содержит значение, указывающее на время в миллисекундах, через
которое всплывающая подсказка будет скрыта.
property HintPause: integer;
Свойство содержит значение, указывающее на время в миллисекундах, в
течение которого будет отображаться всплывающая подсказка.
property
HintShowCuts: Boolean;
Свойство позволяет отображать во всплывающей
подсказке "быстрые клаыиши". Если свойство имеет значение true, то комбинация
клавиш отображается, если false – нет.
property HintShortPause: integer;
Свойство содержит значение, указывающее на время в миллисекундах, в
течение которого будет отображаться всплывающая подсказка, если уже отображена
другая всплывающая подсказка.
property Icon: TIcon;
Значок,
который будет использоваться операционной системой для идентификации данного
приложения.
property MainForm: TForm;
Свойство определяет
главную форму приложения.
property NonBiDiKeyboard: string;
Свойство содержит название раскладки клавиатуры, которая должна
использоваться, если текст читается слева направо. (Ro)
property
ShowHint: Boolean;
Свойство определяет возможность появления всплывающих
подсказок. Если свойство имеет значение true, то всплывающие подсказки
появляются, если false – нет.
property ShowMainForm: Boolean;
Свойство определяет возможность отображения главной формы. Если свойство
имеет значение true, то главной является форма, которая была главной при
разработке. Если главной должна быть другая форма, то этому свойству необходимо
присвоить значение false, а свойству MainForm – имя новой главной формы.
Свойству Visible формы, которая была главной, необходимо присвоить значение
false.
property Terminated: Boolean;
Свойство указывает на
завершение работы приложения. Этому свойству присваивается значение true, если
Windows посылает ему сообщение WM_QUIT, означающее, что приложение должно
завершить работу. (Ro)
property Title: string;
Свойство содержит
строковое выражение, являющееся заголовком приложения. Этот заголовок, например,
отображается на кнопке панели задач Windows.
property
UpdateFormatSetting: Boolean;
Свойство указыва5ет на возможность
автоматического изменения формата при пользовательском изменении конфигурации
опеарционной системы. Если свойство имеет значение true, то изменение
выполняется автоматически.
property UpdateMetricSettings: Boolean;
Свойство указывает на возможность изменения шрифтов окна подсказки и
заголовка значка.
.procedure ActivateHint (CursorPos: TPoint);
Метод позволяет отобразить всплывающую подсказку в заданной точке
CursorPos.
procedure BringToFront;
Метод позволяет переместить
последнее из активных окон приложения на передний план.
procedure
CancelHint;
Метод позволяет убрать всплывающую подсказку.
procedure ControlDestroyed (Control: TControl);
Метод
предназначен для внутреннего использования и вызывается автоматически объектом
типа TControl.
procedure CreateForm (FormClass: TformClass; var
Reference);
Метод позволяет динамически создать новую форму FormClass.
По умолчанию форма, созданная первым вызовом метода CreateForm, становится
главной формой приложения.
procedure HandleExeption (Sender: TObject);
Метод предназначен для обработки исключений по умолчанию. Этот метод
вызывается, когда в программе не был найден обработчик соответствующего
исключения. Метод прерывает выполнение приложения и выдает информационное окно с
описанием возникшей ошибки.
procedure HandleMessage;
Метод
позволяет прервать выполнение приложения для обработки одного системного
сообщения Windows, предоставляя системе возможность выполнять иные действия в
ситуациях, когда в приложении выполняются длительные операции, например сложные
вычмсления.
function HelpCommand (Command: Word; Data: LongInt):
Boolean;
Метод позволяет выполнить быстрый доступ к любой из справочных
команд в WinHelp API. Перед отправкой команды Command метод HelpCommand
генерирует исключение OnHelp для активной формы или объекта TApplication. О
возможных командах справки Windows можно узгать в справочной информации Windows
по ключу WinHelp.
function HelpContext (Context: THelpContext): Boolean;
type THelpContext = -MaxLongInt..MaxLongInt;
Метод позволяет
отобразить указанный раздел Context справочной системы. Если раздел был удачно
отображен, то метод возвращает значение true.
function HelpJump (const
JumpID: string): Boolean;
Метод позволяет отобразить указанный раздел
JumpID справочной системы. Если раздел был удачно отображен, то метод возвращает
значение true.
procedure HideHint;
Метод позволяет скрыть
текущую всплывающую подсказку.
procedure HintMouseMessage (Control:
TControl; var Message: TMessage);
Метод предназначен для внутреннего
пользования и позволяет управлять расположением окна подсказки.
procedure HookMainWindow (Hook: TWindowHook);
type TWindowHook =
function (var Message: Tmessage): Boolean of object;
Метод позволяет
создать перехватчик системных сообщений.
procedure Initialize;
Метод позволяет инициализировать все подсистемы, определенные для
данного приложения. Этот метод при загрузке проекта выполняется первым.
function IsRightToLeft: Boolean;
Метод возвращает значение true,
если в приложении используется обход элементов управления в режиме справа
налево.
function MessageBox (const Text, Caption: Pchar; Flags:
LongInt): integer;
Метод позволяет создать стандартное окно диалога.
Подробнее
procedure Minimize;
Метод позволяет свернуть все
открытые окна приложения.
procedure NormalizeAllTopMosts;
Метод
позволяет перевести все окна приложения из состояния "всегда поверх остальных
окон" в нормальное состояние.
procedure NormalizeTopMosts;
Метод
позволяет перевести все окна приложения за исключением главного окна из
состояния "всегда поверх остальных окон" в нормальное состояние.
procedure ProcessMessages;
Метод позволяет прервать выполнение
приложения для обработки всех системных сообщений Windows, стоящих в очереди.
Этот метод позволяет выполнять системе иные действия в ситуациях, когда в
приложении выполняются длительные операции, например, сложные вычисления.
procedure Restore;
Метод позволяет восстановить все свернутые
окна приложения до нормального размера.
procedure RestoreTopMosts;
Метод позволяет восстановить все открытые окна приложения, находящиеся в
нормальном состоянии, в состояние "поверх всех". Данный метод применим только к
тем окнам, свойство FormStyle которых имеет значение fsStayOnTop.
procedure Run;
Метод предназначен для внутреннего использования
и позволяет начать выполнение приложения. Этот метод вместе с методом
инициализации (Initialize) и методом создания главной формы (CreateForm)
автоматически записывается в основном блоке программы при создании ее заготовки.
procedure ShowExeption (E: Exeption);
Метод позволяет вывести
информационное окно с сообщением, описывающим заданную исключительную ситуацию
E.
procedure Terminate;
Метод позволяет завершить работу
приложения.
function UpdateAction (Action TbasicAction): Boolean;
reintroduce;
Метод позволяет генерировать событие OnActiveUpdate.
function UseRightToLeftAlignment: Boolean;
Метод возвращает
значение true, если для выравнивания объектов используется режим ""права
налево". Этот метод требуется для проверки приложений в ближневосточных версиях
Windows, когда свойство BiDiMode имеет значение bdRightToLeft. Во всех остальных
случаях метод возвращает значение false.
function UseRightToLeftReadinf:
Boolean;
Метод возвращает значение true, если для вывода текстовой
информации используется режим ""права налево". Этот метод требуется для проверки
приложений в ближневосточных версиях Windows, когда свойство BiDiMode имеет
значение bdRightToLeft. Во всех остальных случаях метод возвращает значение
false.
procedure UnhookMainWindow (Hook: TwindowHook);
Метод
позволяет удалить перехватчик системных сообщений Hook, созданный методом
HookMainWindow.
function UseRightToLeftScrollBar: Boolean;
Метод
возвращает значение true, если полосы прокрутки элементов управления должны
отображаться с левой стороны. Этот метод используется для проверки приложений в
ближневосточных версиях Windows, когда свойство BiDiMode имеет значение
bdRightToLeft. Во всех остальных случаях метод возвращает значение false.
property OnActionExecute: TActionEvent;
Событие генерируется,
если вызван, но не обработан метод Execute.
property OnActionUpdate:
TActionEvent;
Событие генерируется, если вызван, но не обработан метод
Update.
property OnActivate: TNotifyEvent;
Событие генерируется,
когда приложение становится активным.
property OnDeactivate:
TNotifyEvent;
Событие генерируется, когда приложение становится
неактивным.
property OnException: TExceptionEvent;
type
TExceptionEvent = procedure (Sender: TObject; E: Exception) of object;
Событие генерируется, когда в приложении возбуждается исключительная
ситуация, которая не может быть программно обработана в блоке try…except.
property OnHelp: THelpEvent;
type THelpEvent = function
(Command: Word; Data: LongInt; var CallHelp: Boolean): Boolean of object;
Событие генерируется, когда в приложении возникает запрос на получение
справочной информации.
property OnHint: TNotifyEvent;
Событие
генерируется, когда указатель мыши помещается на элемент управления, имеющий
всплывающую подсказку.
property OnIdle: TIdleEvent;
type
TIdleEvent = procedure (Sender: TObject; var Done: Boolean): of object;
Событие генерируется, когда приложение находится в режиме ожидания, не
выполняя никаких действий. Например, ожидается ввод данных. property
OnMessage: TMessageEvent;
type TMessageEvent = procedure (var Msg: TMsg;
var Handled: Boolean): of object;
Событие генерируется, когда приложение
получает состемное сообщение от операционной системы.
property
OnMinimize: TNotifyEvent;
Событие генерируется, когда окна приложения
минимизируются.
property OnRestore: TNotifyEvent;
Событие
генерируется, когда окна приложения восстанавливаются из свернутого приложения
до нормального размера.
property OnShortCut: TShortCutEvent;
type TShortCutEvent = procedure (var Msg: TWMKey; var Handled: Boolean):
of object;
Событие генерируется, когда пользователь нажимает на
клавиатуре клавишу. Это событие генерируется первым из всех событий, связанных с
обработкой нажатия клавиши: OnKeyDown, OnKeyPress и OnKeyUp.
property
OnShowHint: TShowHintEvent;
type TShowHintEvent = procedure (var
HintStr: string; var CanShow: Boolean; var HintInfo: THintInfo): of object;
Событие генерируется, когда приложение готовится вывести всплывающую
подсказку. Параметр HintStr определяет текст подсказки, параметр CanShow –
возможность отображения подсказки, а параметр HintInfo содержит информацию о
внешнем виде и поведении окна справки.
При минимизации формы я использую RxTrayIcon, чтобы при этом исчезла кнопка
из Панели задач вызываю ShowWindow(Application.Handle,SW_HIDE). Но вот
незадача - не получается при восстановлении приложения (после клика на
TrayIcon) добиться, чтобы оно становилось поверх других окон и обязательно было
активным.
Дело оказалось в следующем : гасить Tray-иконку надо в
последнюю очередь, именно так все работает(ранее сначала гасил Tray-иконку,
а уже потом восттанавливал свое приложение). Таким образом правильно
работает следующий код:
procedure TForm1.ApplicationMinimize(Sender : TObject);
begin RxTrayIcon1.Show; ShowWindow(Application.Handle,SW_HIDE); end;
procedure TForm1.RxTrayIcon1Click(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer); begin Application.Restore; SetForeGroundWindow(Application.MainForm.Handle);
RxTrayIcon1.Hide; end; Авторы
ответа:Song,
Den Взято с
Vingrad.ru http://forum.vingrad.ru
Если навсегда - то поставить у формы FormStyle свойство в fsStayonTop, если
надо чтобы просто программа была установлена в активное состояние (как будто
кликнули на ней на таскбаре) - Application.BringtoFront
Кроме того
можно играться API функцией ShowWindow передавая ей Form1.Handle, или
Application.Handle и один из кучи параметров - посмотри на нее Help - там много
вариантов. Автор
ответа:Vit Взято с
Vingrad.ru http://forum.vingrad.ru
Всё, что нам нужно, это HRGN и дескриптор (handle) элемента управления.
SetWindowRgn имеет три параметра: дескриптор окна, которое будем менять,
дескритор региона и булевый (boolean) параметр, который указывает -
перерисовывать или нет после изменения. Как только у нас есть дескриптор и
регион, то можно вызвать SetWindowRgn(Handle, Region, True) и вуаля!
Здесь приведён пример использования функции BitmapToRgn (описанной в
примере Как создать регион(HRNG) по маске).
Заметьте, что Вы не должны
освобождать регион при помощи DeleteObject, так как после вызова SetWindowRgn
владельцем региона становится операционная система.
var MaskBmp: TBitmap; begin MaskBmp := TBitmap.Create; try MaskBmp.LoadFromFile('FormShape.bmp');
Height := MaskBmp.Height; Width := MaskBmp.Width;
// ОС владеет регионом, после вызова SetWindowRgn SetWindowRgn(Self.Handle, BitmapToRgn(MaskBmp), True); finally MaskBmp.Free; end; end;
Взято с
Исходников.ru http://www.sources.ru/delphi_src1.shtml
procedure TForm1.CreateParams(var Params: TCreateParams);
begin inherited CreateParams(Params);
{ удаляем заголовок и рамку } Params.Style := Params.Style or ws_popup xor ws_dlgframe;
end;
procedure TForm1.FormCreate(Sender: TObject);
var FormRgn: hRgn; begin {clear form} Form1.Brush.Style := bsSolid; //bsclear; { делаем круг формы } GetWindowRgn(Form1.Handle, FormRgn);
{ удаляем старый объект } DeleteObject(FormRgn); { делаем прямоугольник формы } Form1.Height := 500;
Form1.Width := Form1.Height; { создаём круглую форму } FormRgn := CreateRoundRectRgn(1, 1, Form1.Width - 1,
Form1.height - 1, Form1.width, Form1.height);
{ устанавливаем новое круглое окно } SetWindowRgn(Form1.Handle, FormRgn, TRUE); end;
procedure TForm1.Button1Click(Sender: TObject);
begin Form1.close; end;
procedure TForm1.Button4Click(Sender: TObject);
var HRegion1, Hreg2, Hreg3: THandle; Col: TColor; begin ShowMessage ('Ready for a real crash?');
Col := Color; Color := clRed; PlaySound ('boom.wav', 0, snd_sync);
HRegion1 := CreatePolygonRgn (Pts, sizeof (Pts) div8,
alternate); SetWindowRgn ( Handle, HRegion1, True);
ShowMessage ('Now, what have you done?');
Color := Col; ShowMessage ('Вам лучше купить новый монитор'); end;
Взято с
Исходников.ru http://www.sources.ru/delphi_src1.shtml
Пример показывает, как при инициализации формы
происходит поиск нашего окна, а затем вычисление местоположения нужной нам
кнопки в заголовке окна.
procedure TForm1.FormCreate(Sender: TObject);
var hwndHandle: THANDLE; hMenuHandle: HMENU;
iPos: Integer;
begin hwndHandle := FindWindow(nil, PChar(Caption));
if (hwndHandle <> 0) then begin hMenuHandle := GetSystemMenu(hwndHandle, FALSE); if (hMenuHandle <> 0) then begin DeleteMenu(hMenuHandle, SC_CLOSE, MF_BYCOMMAND);
iPos := GetMenuItemCount(hMenuHandle); Dec(iPos);
{ Надо быть уверенным, что нет ошибки т.к. -1 указывает на ошибку } if iPos > -1then DeleteMenu(hMenuHandle, iPos, MF_BYPOSITION); end;
end; end;
Взято с
Исходников.ru http://www.sources.ru/delphi_src1.shtml
В примере показывается, как изменять
заголовок окна (видимый в списке задач при переключении между приложениями) при
минимизации окна в иконку.
Сперва необходимо определить сообщение
поумолчанию:
Const DefMsgNorm = 'MyApp version 1.0';
DefMsgIcon = 'MyApp. (Use F12 to turn of)';
И
добавить две глобальных переменных:
Var ActMsgNorm : String;
ActMsgIcon : String;
Затем
при открытии основной формы инициализируем переменные из констант.
Procedure TFormMain.FormCreate( Sender : TObject );
Begin ActMsgNorm := DefMsgNorm; ActMsgIcon := DefMsgIcon;
Application.Title := ActMsgNorm; End;
Затем
достаточно в обработчик OnResize добавить следующий код:
Procedure TFormMain.FormResize( Sender : TObject );
Begin If ( FormMain.WindowState = wsMinimized ) Then Application.Title := ActMsgIcon Else Application.Title := ActMsgNorm; End;
Чтобы добавить дополнительную кнопку, нам прийдётся
создать обработчики для следующих событий: WM_NCPAINT;//вызывается, когда
перерисовывается не клиентская область формы WM_NCACTIVATE; вызывается,
когда заголовок формы становится активныи WM_NCLBUTTONDOWN; вызывается,
когда кнопка мыши нажимается на не клиентской области WM_NCMOUSEMOVE;
вызывается, когда курсор мыши передвигается по не клиентской области
WM_MOUSEMOVE;вызывается, когда курсор мыши передвигается по клиентской
области WM_LBUTTONUP; вызывается, когда кнопка мыши отпушена в клиентской
области WM_NCLBUTTONUP; вызывается, когда кнопка мыши отпушена в не
клиентской области WM_NCLBUTTONDBLCLK; вызывается при двойном щелчке мышкой
в не клиентской области
Приведённый ниже код модифицирован, чтобы
избавиться от нежелательного мерцания кнопки будем использовать следующие
переменные:
h1(Thandle) : хэндл контекста устройства всего окна, включая
не клиентскую область. pressed(boolean): индикатор, показывающий, нажата
кнопка или нет. focuslost(boolean): индикатор, показывающий, находится ли
фокус на кнопке или нет. rec(Trect): размер кнопки.
var Form1: TForm1; h1:thandle; pressed:boolean;
focuslost:boolean; rec:trect; implementation
{$R *.DFM}
procedure tform1.WMLBUTTONUP(var msg:tmessage);
begin pressed:=false; invalidaterect(form1.handle,@rec,true); inherited; end;
procedure tform1.WMMOVE(var msg:tmessage);
var tmp:boolean begin tmp:=focuslost; focuslost:=true; if tmp<>focuslost then invalidaterect(form1.handle,@rec,true); inherited; end; procedure tform1.WMNCMOUSEMOVE(var msg:tmessage);
var pt1:tpoint; tmp:boolean; begin tmp:=focuslost; pt1.x:=msg.LParamLo-form1.left;
pt1.y:=msg.LParamHi-form1.top; ifnot(ptinrect(rec,pt1)) then focuslost:=true else focuslost:=false; if tmp<>focuslost then invalidaterect(form1.handle,@rec,true); end;
procedure tform1.WNCLBUTTONDBLCLICK(var msg:tmessage);
var pt1:tpoint; begin pt1.x:=msg.LParamLo-form1.left; pt1.y:=msg.LParamHi-form1.top;
ifnot(ptinrect(rec,pt1)) then inherited; end;
procedure tform1.WMNCMOUSEUP(var msg:tmessage);
var pt1:tpoint; begin pt1.x:=msg.LParamLo-form1.left; pt1.y:=msg.LParamHi-form1.top;
if (ptinrect(rec,pt1)) and (focuslost=false) then begin pressed:=false; {
enter your code here when the button is clicked
} invalidaterect(form1.handle,@rec,true); end else begin pressed:=false; focuslost:=true; inherited; end; end; procedure tform1.WMNCMOUSEDOWN(var msg:tmessage);
var pt1:tpoint; begin pt1.x:=msg.LParamLo-form1.left; pt1.y:=msg.LParamHi-form1.top;
if ptinrect(rec,pt1) then begin pressed:=true; invalidaterect(form1.handle,@rec,true);
end else begin form1.paint; inherited; end; end;
procedure tform1.WMNCACTIVATE(var msg:tmessage);
begin invalidaterect(form1.handle,@rec,true); inherited; end;
procedure tform1.WMNCPAINT(var msg:tmessage);
begin invalidaterect(form1.handle,@rec,true); inherited; end;
procedure TForm1.FormPaint(Sender: TObject);
begin h1:=getwindowdc(form1.handle); rec.left:=form1.width-75;
rec.top:=6;
rec.right:=form1.width-60;
rec.bottom:=20;
selectobject(h1,getstockobject(ltgray_BRUSH));
rectangle(h1,rec.left,rec.top,rec.right,rec.bottom); if (pressed=false) or (focuslost=true) then drawedge(h1,rec,EDGE_RAISED,BF_RECT) elseif (pressed=true) and (focuslost=false) then drawedge(h1,rec,EDGE_SUNKEN,BF_RECT); releasedc(form1.handle,h1);
end;
procedure TForm1.FormResize(Sender: TObject);
begin form1.paint; end;
Дата: 25 Августа 2000г. Автор: NeNashev nashev@mail.ru
InvalidateRect на событие Resize ничего не даёт. Но даже без него
кнопка всё равно моргает при Resize формы... Надо ещё где-то убрать
Для рисования кнопок на заголовке окна лучше пользоваться
DrawFrameControl а не DrawEdge... Так и с не серыми настройками
интерфейса всё правильно будет. Да и проще так.
Названия функций,
констант и т.п лучше писать так, как они в описаниях даются, а не подряд
маленькими буквами. Особенно для публикации. Так оно и читается по большей
части лучше, и в С такая привычка Вам не помешает...
Сравнивать
логическое значение с логической константой чтоб получить логическое
значение глупо, так как логическое значение у Вас уже есть. тоесь вместо
if (pressed=true) and (focuslost=false) лучше писать if Pressed and
not FocusLost
Для конструирования прямоугольников и точек из координат
есть две простые функции Rect и Point.
В общем Ваша процедура
FormPaint может выглядеть так:
procedure TMainForm.FormPaint(Sender: TObject);
var h1:THandle; begin h1:=GetWindowDC(MainForm.Handle); rec:=Rect(MainForm.Width-75,6,MainForm.Width-60,20); if Pressed andnot FocusLost
then DrawFrameControl(h1, rec, DFC_BUTTON, DFCS_BUTTONPUSH or DFCS_PUSHED)
else DrawFrameControl(h1, rec, DFC_BUTTON, DFCS_BUTTONPUSH);
ReleaseDC(MainForm.Handle,h1); end;
Но
вообще-то рисовать эту кнопку надо только при WM_NCPAINT, а не всегда... И
вычислять координаты по другому... Вдруг размер элементов заголовка у юзера
в системе не стандартный? А это просто настраивается...
Что такое MDI?
MDI расшифровывается как multiple document interface (многодокументный
интерфейс). В приложениях с MDI, в основном (родительском) окне можно окрыть
более одного дочернего окна. Данная возможность обычно используется в
электронных таблицах или текстовых редакторах.
Каждое MDI приложение
имеет три основные составляющие: Одну (и только одну) родительскую форму
MDI, Одну и более (обычно больше) дочерних форм MDI, и основное меню MDI.
MDI "мать" Как уже упоминалось, в проекте MDI приложения
может присутствовать только один MDI контейнер (родительская форма) и он должен
быть стартовой формой. Для создания основного окна MDI приложения проделайте
следующие шаги:
Запустите Delphi и выберите File | New Application...
Delphi создаст новый проект с одной формой под названием form1 (по умолчанию).
В свойстве Name присвойте форме имя frMain. Установите свойство
FormStyle в fsMDIform. Сохраните этот проект (имя проекта на Ваше
усмотрение, например prMDIExample), вместе с uMain.pas в только что созданной
директории. Как Вы успели заметить, для создания основной формы MDI, мы
установили свойство FormStyle в fsMDIform. В каждом приложении только одна форма
может иметь свойство fsMDIform.
MDI "дети" Каждое
родительское окно MDI нуждается по крайней мере в одной дочерней форме. Дочерние
формы MDI - это простые формы, за исключением того, что их видимая часть
ограничена размерами родительского окна. Так же при минимизации такого окна, оно
помещается не в панель задач, а остаётся внутри родительского окна ( на панель
задач попадёт только родительское окно).
Теперь давайте создадим
дополнительные формы, а точнее дочерние. Просто выберите File | New Form. Будет
создан новый объект формы с именем form1 (по умолчанию). При помощи Object
Inspector измените свойство Name в форме form1 на frChild, а свойство FormStyle
на fsMDIChild. Сохраните эту форму с соответствующим ей файлом как uchild.pas.
Обратите внимание, что при помощи данного свойства мы можем превратить любую
существующую форму в дочернюю форму MDI. Ваше приложение может включать
множество дочерних MDI форм такого же или другого типа.
Так же хочется
обратить Ваше внимание, что MDI приложение может включать в себя и самые обычные
формы, но в отличие от дочерних, они будут отображаться как обычные модальные
диалоговые окна (такие как about box, или файловый диалог).
Естевственно, что как на родительском так и на дочернем окнах можно
располагать любые элементы управления, однако уже давно сложилась традиция, что
на родительской форме располагается панель статуса (status bar) и панель
инструментов (toolbar), в то время как на дочерних формах располагаются все
остальные контролы, такие как гриды, картинки, поля вводи и т. д.
Автосодание -> Доступные Теперь давайте произведём
некоторые настройки нашего проекта. Выберите Project | Options, откроется диалог
опций проекта (Project Options). В левой панели выберите frChild (Авто-создание
форм ("Auto-create forms")), и переместите её в правую панель (Доступные формы
(Available forms)). Список правой панели содержит те формы, которые используются
Вашим приложением, но которые не созданы автоматически. В MDI приложении, по
умолчанию, все дочерние формы создаются автоматически и отображаются в
родительской форме.
Создание и отображение... Как упомянуто
выше, настройка не позволяет автоматически создавать дочерние окна, поэтому нам
необходимо добавить некоторый код, который будет производить создание объекта
формы frChild. Следующую функцию CreateChildForm необходимо поместить внутри
основной формы (MDI родитель) (наряду с заголовком в interface's private):
uses uchild;
... procedure TfrMain.CreateChildForm
(const childName : string); var Child: TfrChild;
begin Child := TfrChild.Create(Application); Child.Caption := childName;
end;
Данный
код создаёт одну дочернюю форму с заголовком childName. Не забудьте, что
этот код находится разделе "uses uchild".
На закрытие не минимизировать!
Закрытие дочернего окна в MDI приложении всего навсего минимизирует его в
клиентской области родительского окна. Поэтому мы должны обеспечить процедуру
OnClose, и установить параметр Action в caFree:
procedure TfrChild.FormClose
(Sender: TObject; var Action: TCloseAction);
begin Action := caFree; end;
Обратите
внимание, что если форма является дочерней формой MDI, и её свойство BorderIcons
установлено в biMinimize (по умолчанию), то опять же по умолчанию параметр
Action установлен в caMinimize. Если же в дочерней форме MDI нет этих установок,
то по умолчанию Action установлен как caNone, означающий, что при закрытии формы
ничего не случится.
MDI родительское меню Каждое MDI
приложение должно иметь основное меню с (если больше ничего нет), опцией
выравнивания окон. Поскольку мы предварительно переместили дочернюю форму из
Авто-создаваемых (Auto-create) в Доступные (Available) формы, то нам нужен будет
код, который (пункт меню) будет создавать дочерние формы.
Для создания
дочерних окон в нашем приложении будет использоваться пункт меню "New child".
Второе меню (Window) будет использоваться для выравнивания дочерних окошек
внутри родительского окна-формы.
...Создать и отобразить В
заключении нам необходимо сделать обработчик для пункта меню "New child". При
нажатии на пунк меню File | New Child нашего приложения, будет вызываться
процедура NewChild1Click которая в свою очередь будет вызывать процедуру
CreateChildForm (приведённую выше), для создания (следующего) экземпляра формы
frChild.
procedure TfrMain.NewChild1Click(Sender: TObject);
begin CreateChildForm('Child '+IntToStr(MDIChildCount+1)); end;
Только
что созданная дочерняя форма будет иметь заголовок в виде "Child x", где x
представляет количество дочерних форм внутри MDI формы, как описано ниже.
Закрыть всё При работе с приложением, имеющим
многодокументный интерфейс, всегда необходимо иметь процедуру, закрывающую все
дочерние окна.
procedure TfrMain.CloseAll1Click(Sender: TObject);
var i: integer;
begin for i:= 0to MdiChildCount - 1do MDIChildren[i].Close; end;
Вам
прийдётся выполнять проверку на предмет наличия несохранённой информации в
каждом дочернем окне. Для решения данной задачи лучше всего использовать
обработчик события OnCloseQuery.
Свойства MdiChildCount и MDIChildren
MdiChildCount свойство read only, содержащее в себе количество созданных
дочерних окошек. Если не создано ни одно дочернее окно, то это свойство
установлено в 0. Нам прийдётся частенько использовать MdiChildCount наряду с
массивом MDIChildren. Массив MDIChildren содержит ссылки на объекты TForm всех
дочерних окошек.
Обратите внимание, что MDIChildCount первого созданного
дочернего окна равен 1.
Меню Window Delphi обеспечивает
большинство команд, которые можно поместить внутри пункта меню Window. Далее
приведён пример вызова трёх основных методов для команд, которые мы поместили в
наше приложение:
procedure TfrMain.Cascade1Click(Sender: TObject);
begin Cascade;
end;
procedure TfrMain.Tile1Click(Sender: TObject);
begin Tile;
end;
procedure TfrMain.ArrangeAll1Click(Sender: TObject);
begin ArrangeIcons; end;
Если в дочерней форме MDI установить BorderStyle в bsNone, то заголовок формы не
исчезнет. (Об этом сказано в хелпе). А вот следующий пример решает эту проблему:
type ... = class(TForm)
{ other stuff above } procedure CreateParams(var Params: TCreateParams); override; { other stuff below } end;
...
Procedure tMdiChildForm.CreateParams( var Params : tCreateParams ) ;
Begin Inherited CreateParams( Params ) ;
Params.Style := Params.Style and (not WS_CAPTION) ;
End;
Взято с
Исходников.ru http://www.sources.ru/delphi_src1.shtml
(Перевод одноимённой статьи с сайта delphi.about.com )
В Windows
основной элемент пользовательского интерфейса - форма. В Delphi каждый проект
имеет по крайней мере одно окно - главное окно приложения. Все окна в Delphi
основаны на объекте TForm. В данной статье мы рассмотрим основные события
учавствующие в "жизни формы".
Форма Формы имеют свои
свойства, события и методы, при помощи которых Вы можете управлять видом и
поведением формы. Форма, это обычный компонент Delphi, но в отличие от других,
её нет на панели компонентов. Обычно форма создаётся при создании нового проекта
(File | New Application). Вновь созданная форма будет главной формой приложения.
Дополнительные формы в проекте создаются через File | New Form. Так же
существуют и другие способы создания форм, но здесь мы не будем рассматривать
их...
Как и любой другой компонент (объект) форма имеет свои методы и
реагирует на события. Давайте рассмотрим некоторые из этих событий...
OnCreate Событие OnCreate возникает при создании TForm и
только один раз. При создании формы (у каторой свойство Visible установлено в
True), события произойдут в следующем порядке: OnCreate, OnShow, OnActivate,
OnPaint. В обработчике события OnCreate можно сделать какие-либо
инициализационные действия, однако, любые объекты созданные в OnCreate будут
уничтожены в событии OnDestroy.
OnShow Это событие
генерируется, когда форма станет видимой. OnShow вызывается сразу перед тем, как
форма станет видимой. Это событие случается, если установить свойство формы
Visible в True, либо при вызове методов Show или ShowModal.
OnActivate Это событие генерируется, когда форма становится
активной, тоесть когда форма получает фокус ввода. Это событие можно
использовать для того, чтобы сменить элемент формы который должен получить
фокус.
OnPaint, OnResize Эти события вызываются каждый раз,
когда форма изначально создаётся. При этом OnPaint вызывается каждый раз, когда
какому-нибудь элементу формы необходимо перерисоваться (это событие можно
использовать, если необходимо при этом рисовать на форме что-то особенное).
Жизнь Когда форма создана и все её элементы ждут своих
событий, чтобы обрабатывать их, жизнь формы продолжается до тех пор, пока
кто-нибудь не нажмёт крестик в верхнем правом углу формы!
Уничтожение При уничтожении формы, события генерируются в
следующем порядке:
OnCloseQuery Если мы попытаемся закрыть
форму при помощи метода Close либо другим доступным способом (Alt+F4 либо через
системное меню), то сгенерируется событие OnCloseQuery. Таким образом, это
событие можно использовать, чтобы предотвратить закрытие формы. Обычно, событие
OnCloseQuery используется для того, чтобы спросить пользователя - уверен ли он
(возможно в приложении остались несохранённые данные).
procedure TForm1.FormCloseQuery
(Sender: TObject; var CanClose: Boolean);
begin if MessageDlg('Really close this window?',
mtConfirmation, [mbOk, mbCancel], 0) = mrCancel then CanClose := False; end;
Обработчик
события OnCloseQuery содержит переменную CanClose, которая определяет, можно ли
форме закрыться. Изначальное значение этой переменной True. Однако в обработчике
OnCloseQuery можно установить возвращаемое значение CloseQuery в False, чтобы
прервать выполнение метода Close.
OnClose Если OnCloseQuery
вернул CanClose=True (что указывает на то, что форма должна быть закрыта), то
будет будет сгенерировано событие OnClose. Событие OnClose даёт последний
шанс, чтобы предотвратить закрытие формы. Обработчик OnClose имеет параметр
Action со следующими четырьмя возможными значениями: caNone. Форме не
разрешено закрыться. Всё равно, что мы установим CanClose в False в
OnCloseQuery. caHide. Вместо закрытия, форма будет скрыта. caFree. Форма
будет закрыта, и занятые ей ресурсы будут освобождены. caMinimize. Вместо
закрытия, форма будет минимизирована. Это значение устанавливается поумолчанию у
дочерних форм MDI.
Замечание: Когда пользователь шутдаунит Windows, то
будет вызвано OnCloseQuery, а не OnClose. Если Вы не хотите, чтобы Windows
завершила свою работу, то поместите свой код в обработчик события OnCloseQuery,
хотя CanClose=False не сделает, того, что сделано здесь.
OnDestroy После того, как метод OnClose будет обработан и
форма будет закрыта, то будет вызвано событие OnDestroy. В OnCreate обычно
делаются действия, противоположные тем, которые проделывались в OnCreate, то
есть уничтожение созданных объектов и освобождение выделенной памяти.
Естевственно, что когда главная форма проекта будет закрыто, то
приложение будет завершено.
В статье рассматривается
приём создания обработчиков сообщений, которые позволяют форме при
перетаскивании "прилипать" к краям экранной области.
Конечно же в Win
API такой возможности не предусмотрено, поэтому мы воспользуемся сообщениями
Windows. Как нам извесно, Delphi обрабатывает сообщения через события, генерируя
его в тот момент, когда Windows посылает сообщений приложению. Однако некоторые
сообщения не доходят до нас. Например, при изменении размеров формы,
генерируется событие OnResize, соотвествующее сообщению WM_SIZE, но при
перетаскивании формы никакой реакции не происходит. Конечно же форма может
получить это сообщение, но изначально никаких действий для данного сообщения не
предусмотрено.
Итак, при перемещении, окну посылается сообщение
WM_MOVING. Обрабатывая данной сообщение, приложение может отслеживать размер и
расположение перетаскиваемого квадрата и, при необходимости, изменять их.
Так же существует сообщение WM_WINDOWPOSCHANGING, которое посылается
окну, в случае, если его размер, расположение или место в Z порядке собираются
измениться, как результат вызова функции SetWindowPos либо другой функции
управления окном.
Чаще всего с сообщением передаются дополнительные
параметры, которые сообщают нам необходимую информацию. Например, сообщение
WM_MOVE, указывающее на то, что форма изменила своё местоположение, так же
передаёт в параметре LPARAM новые координаты X и Y.
Сообщение
WM_WINDOWPOSCHANGING передаёт нам ТОЛЬКО один параметр - указатель на структуру
WindowPos, которая содержит информацию о новом размере и местоположении окна.
Вот как выглядит структура WindowPos:
TWindowPos = packedrecord hwnd: HWND; {Identifies the window.} hwndInsertAfter: HWND; {Window above this one} x: Integer; {Left edge of the window} y: Integer; {Right edge of the window} cx: Integer; {Window width} cy: Integer; {Window height} flags: UINT; {Window-positioning options.} end;
Наша
задача проста: нам необходима, чтобы форма прилипла к краю экрана, если она
находится на определённом расстоянии от окна (допустим 20 пикселей).
Пример К новой форме добавьте Label, один контрол Edit и четыре
Check boxes. Измените имя контрола Edit на edStickAt. Измените имена чекбоксов
на chkLeft, chkTop, и т.д... Для установки количества пикселей используем
edStickAt, который будет использоваться для определения необходимого расстояния
до края экрана достаточного для приклеивания формы.
Нас интересует
только одно сообщение WM_WINDOWPOSCHANGING. Обработчик для данного сообщения
будет объявлен в секции private. Ниже приведён полный код этого процедуры
"прилипания" вместе с комментариями. Обратите внимание, что Вы можете
предотвратить "прилипание" формы к определённому краю, путё снятия нужной
галочки.
Для получения рабочей области декстопа (минус панель задач,
панель Microsoft и т.д.), используем SystemParametersInfo, первый параметр
которой SPI_GETWORKAREA.
with Msg.WindowPos^ dobegin if chkLeft.Checked then if x <= rWorkArea.Left + StickAt thenbegin x := rWorkArea.Left; Docked := TRUE; end;
if chkRight.Checked then if x + cx >= rWorkArea.Right - StickAt thenbegin x := rWorkArea.Right - cx; Docked := TRUE; end;
if chkTop.Checked then if y <= rWorkArea.Top + StickAt thenbegin y := rWorkArea.Top; Docked := TRUE; end;
if chkBottom.Checked then if y + cy >= rWorkArea.Bottom - StickAt thenbegin y := rWorkArea.Bottom - cy; Docked := TRUE; end;
if Docked thenbegin with rWorkArea dobegin // не должна вылезать за пределы экрана if x < Left then x := Left;
if x + cx > Right then x := Right - cx;
if y < Top then y := Top;
if y + cy > Bottom then y := Bottom - cy;
end; {ширина rWorkArea} end; {} end; {с Msg.WindowPos^}
inherited; end; end.
Теперь
достаточно запустить проект и перетащить форму к любому краю экрана.
А
также можно взять готовый пример (~6Kb)
Вот собственно и всё.
Комментарии:
Автор: Nashev
а так короче... И, ИМХО,
лучше:
procedure TCustomGlueForm.WMWindowPosChanging1(var Msg: TWMWindowPosChanging);
var WorkArea: TRect; StickAt : Word; begin StickAt := 10;
SystemParametersInfo(SPI_GETWORKAREA, 0, @WorkArea, 0); with WorkArea, Msg.WindowPos^ dobegin // Сдвигаем границы для сравнения с левой и верхней сторонами Right:=Right-cx; Bottom:=Bottom-cy; if abs(Left - x) <= StickAt then x := Left;
if abs(Right - x) <= StickAt then x := Right;
if abs(Top - y) <= StickAt then y := Top;
if abs(Bottom - y) <= StickAt then y := Bottom;
end; inherited; end;
Скачать
демонстрационный проект с исходниками - 167Kb
В проекте осталось 2
глюка:
1) Если у формы, к которой прицепили другую форму за
правую/нижнюю границы попробовать переместить эти границы, прицепленная форма
останется на месте но все равно будет прикрепленной.
2) Иногда 3 формы
прикрепляются друг к другу, и иначе, как воспользовавшись 1-ым глюком, их не
расцепить.
Состав проекта: сам проект, uCustomGlueForm - форма с
добавленной липкостью 3 формы - пустышки, наследники TCustomGlueForm
Для
использования сделанного в своих проектах надо добавить в проект, и свои формы
создавать, наследуя от него, например, через мастер "File/New..." В
принципе, если липкость нужна без прилипания (а это уже работает без глюков)
можно выкинуть все методы, кроме procedure WMWindowPosChanging(var Msg:
TWMWindowPosChanging);message WM_WINDOWPOSCHANGING; и все переменные, а в
самом WMWindowPosChanging удалить все упоминания этих переменных.
Пример демонстрирует вывод теста случайным образом на
форме под определённым углом. Добавляем в форму компонент TButton и в событие
OnClick следующий код:
procedure TForm1.Button1Click(Sender: TObject);
var logfont:TLogFont; font: Thandle; count: integer;
begin LogFont.lfheight:=20;
logfont.lfwidth:=20;
logfont.lfweight:=750;
LogFont.lfEscapement:=-200;
logfont.lfcharset:=1;
logfont.lfoutprecision:=out_tt_precis;
logfont.lfquality:=draft_quality;
logfont.lfpitchandfamily:=FF_Modern;
for count:=1to100do begin canvas.textout(Random(form1.width),Random(form1.height),'Hello');
SetTextColor(form1.canvas.handle,rgb(Random(255),Random(255),Random
(255)));
end;
Deleteobject(font); end;
Для этого Вам понадобится переопределить процедуру CreateParams у желаемой
формы. А в ней установить params.WndParent в дескриптор окна, к которому Вы
хотите прикрепить форму.
Статусбар, это стандартный элемент управления Windows и как все отображает
шрифт, заданный в параметре clBtnText, который устанавливается через Панель
управления. Поумолчанию этот цвет чёрный, но он может менятся в зависимоти
пользовательской темы. StatusBar и связанные с ним панели имеют возможность
самостоятельной перерисовки (owner-draw), позволяющей рисовать текст различными
цветами. Для этого необходимо в TStatusBar.Panels установить свойство Style в
OwnerDraw.
Корректнее было бы самому канву рисовать, но можно и просто вставить - держи
функцию для этого - применять вместо стандартного метода Create.
Function CreateProgressBar(StatusBar:TStatusBar; index:integer):TProgressBar;
var findleft:integer;
i:integer; begin result:=TProgressBar.create(Statusbar); result.parent:=Statusbar;
result.visible:=true; result.top:=2;
findleft:=0; for i:=0toindex-1do findleft:=findleft+Statusbar.Panels[i].width+1;
result.left:=findleft; result.width:=Statusbar.Panels[index].width-4;
result.height:=Statusbar.height-2; end; Автор
ответа:Vit
Взято с
Vingrad.ru http://forum.vingrad.ru