Здесь удобнее всего использовать имя, состоящее из даты и времени, напри-
мер: 2310566160798 для 23:10:56 16-07-98. Если перевести это число в 32-чную
систему счисления, получим искомые восемь символов имени файла. Это хорошо
использовать, если программа создает много файлов, которые потом будут
ис- пользоваться. Если же нужно создать несколько временных файлов, то
лучше воспользоваться фyнкцией GetTempFileName.
Как использовать
анимированные курсоры в программе?
Пример формы, использующей анимированный курсор:
........................................................
procedure TForm1.Button1Click(Sender: TObject);
var
h : THandle;
begin
h := LoadImage(0,'C:\TheWall\Magic.ani',
IMAGE_CURSOR, 0, 0,
LR_DEFAULTSIZE or LR_LOADFROMFILE);
if h = 0 then ShowMessage('Cursor not loaded')
else
begin
Screen.Cursors[1] := h;
Form1.Cursor := 1;
end;
end;
... ..... ...... ....... ....... ...... ..
Есть
программа на Delphi, котоpая отображает какой-то html. В html используется
gif-файл.
Как в Delphi-пpоекте указать, чтобы этот gif находился в exe как некий
кусок кода. А когда надо будет, записать его обратно в gif-файл без изменений,
выковырнув из exe?
Можно, используя RxLib. После его установки в меню
View появится пунктик Project Resources. Hужно выбрать Project Resources->New->User
Data и добавить нужный файл. В данном случае ресурс был назван "RCDATA_1".
Если RxLib нет, то нужно создать файл описания ресурсов:
=== Begin gifs.rc ===
mygif rcdata "имя_gif-файла.gif"
mygif1 rcdata "RCDATA_1"
=== End dots.rc ===
Потом скомпилировать его командой brcc32 gifs.rc и получить gifs.res В
начало модуля добавь строчку {$R gifs.res}
В своей программе необходимо написать:
var
rs : TResourceStream;
a : Pointer;
begin
rs:=TResourceStream.Create(hinstance,'RCDATA_1',RT_RCDATA);
try
GetMem(a,rs.size);
rs.Read(a^,rs.size); {Теперь a - динамический указатель на код}
{ Здесь делается все, что необходимо с кодом, используя указатель a }
FreeMem(a);
finally
rs.Free;
end;
end;
А можно и так, если необходимо записать ресурс в файл:
var
rs : TResourceStream;
fs : TFileStream;
begin
rs:=TResourceStream.Create(hInstance, 'mygif', RT_RCDATA);
fs:=TFileStream.Create('имя_gif-файла.gif', fmCreate);
try
fs.CopyFrom(rs, rs.Size);
finally
fs.Free;
rs.Free;
end;
end;
Сущность свойства Owner в том, что перед уничтожением владельца,
он уничтожает (через Free) принадлежащие ему объекты. Таким образом, все
зависит от того, кому Вы хотите доверить уничтожение созданных форм/компонентов.
В частности, если Вы сами будете этим заниматься, то AOwner может
быть, например, nil.
Для того, чтобы созданный компонент появился на экране, надо указать его
родителя, заполнив свойство Parent, например:
NewButton.Parent := Form1;
Пример кода, обрабатывающего события от свежесозданных компонентов:
type
TForm1 = class(TForm)
{ ... }
private
{ эта процедура будет вызываться при нажатии на
кнопку }
procedure ButtonClicked(Sender : TObject);
public
{ в этой процедуре происходит создание кнопки
}
procedure CreateButton;
end;
{ ... }
procedure TForm1.CreateButton;
var
Btn : TButton;
begin
Btn := TButton.Create(Self); { Уничтожать кнопку
будет форма }
Btn.Parent := Self; { Родителем кнопки будет форма
}
Btn.OnClick := ButtonClicked; { Процедура, которая
будет исполняться при }
Как
использовать Clipboard для переноса данных в собственном формате?
Не только возможно, именно так поступают функции Clipboard.GetComponent
и Clipboard.SetComponent.
Сперва Вы должны зарегистрировать свой собственный формат данных для Clipboard
с помощью функции RegisterClipboardFormat():
CF_MYFORMAT := RegisterClipboardFormat('My
Format Description');
Далее вы должны выполнить эти шаги : 1. Создать поток (memory
stream) и записать туда данные.
2. Создать глобальный буфер в памяти и скопировать поток туда.
3. Вызвать Clipboard.SetAsHandle(), чтобы поместить буфер в
clipboard.
Пример:
var
HBuf : THandle;
BufPtr : Pointer;
MStream : TMemoryStream;
begin
MStream := TMemoryStream.Create;
try
{-- Write your data to the stream. --}
HBuf := GlobalAlloc(GMEM_MOVEABLE, MStream.Size);
try
BufPtr := GlobalLock(HBuf);
try
Move(MStream.Memory^, BufPtr^, MStream.Size);
Clipboard.SetAsHandle(CF_MYFORMAT, HBuf);
finally
GlobalUnlock(HBuf);
end;
except
GlobalFree(HBuf);
raise;
end;
finally
MStream.Free;
end;
end;
ВНИМАНИЕ: Не уничтожайте буфер, созданный с GlobalAlloc(). Поскольку
Вы поместили его в Clipboard, это уже дело Clipboard'а его уничтожить.
Опять же, получая буфер из Clipboard, не уничтожайте этот буфер - просто
сделайте копию содержимого.
Для обратного получения потока и данных, сделайте что-нибудь вроде этого:
Переключение языка из программы
Для переключения языка применяется вызов LoadKeyboardLayout:
var russian, latin: HKL;
russian:=LoadKeyboardLayout('00000419', 0);
latin:=LoadKeyboardLayout('00000409', 0);
-- -- -- -- -- где то в программе --- --- ---
SetActiveKeyboardLayout(russian);
при помощи SystemParametersInfo
Бывают ситуации, когда вашей программе понадобится отключить реакцию
на клавиши
Ctrl-Alt-Del (например, если вы не хотите, чтобы ее выгрузили из памяти).
Это
можно сделать при помощи функции API SystemParametersInfo, которая
позволяет
узнать, либо установить параметры операционной системы, такие как установки
клавиатуры, дисплея, звука и т.д. Она используется в Панели Управления.
Синтакс
функции следующий:
BOOL SystemParametersInfo(
UINT uiAction, // параметр, который нужно узнать или установить
UINT uiParam, // зависит от действия
PVOID pvParam, // зависит от действия
UINT fWinIni // флаг обновления информации о пользователе
(user profile));
Значение каждого параметра объясняется в Win32 Developer's Reference.
Теперь,
чтобы сделать то, что мы хотим, вызываем следующую прцедуру:
procedure DisableCtrlAltDel;
var
i : integer;
begin
i := 0;
SystemParametersInfo(SPI_SCREENSAVERRUNNING, 1, @i, 0);
end.
Аналогично можно отключить Alt-Tab. Для этого нужно задать SPI_SETFASTTASKSWITCH
в качестве первого параметра функции.
Каким
образом или какой функцией установить системную дату и время Windows 95
средствами Delphi.
Ivanuts V.A. (ivanuts@altavista.net)
31.10.2001 В своих приложениях, которые требуют установки единого времени и даты
на разных машинах, я использую установку системного времени и даты , взятых
путем запроса с сервера БД. У меня это работает вот так:
procedure TGlavMenu.SetSysTime(Sender: TObject);
var
Present : TSystemTime;
Year, Month, Day, Hour, Min, Sec, MSec: Word;
begin
qrTime.Open;{ Этот квери возвращает системное время и дату с сервера БД.
Здесь можно использовать и другие источники - например TEdit и т.д.}
Для Delphi 1. Каждый экземпляр программы имеет ссылку на свою предыдущую
копию - hPrevInst: hWnd. Ее можно проверить перед созданием приложения
и при необходимости отреагировать соответствующим образом. Если запущена
только одна копия, то эта ссылка равна нулю.
Пример:
procedure TForm1.FormCreate(Sender: TObject);
begin
{Проверяем есть ли указатель на предыдущую копию приложения}
IF hPrevInst <> 0 THEN BEGIN
{Если есть, то выдаем сообщение и выходим}
MessageDlg('Программа уже запущена!', mtError, [mbOk], 0);
Halt;
END;
{Иначе - ничего не делаем (не мешаем созданию формы)}
end;
P.S. Для выхода необходимо использовать Halt, а не Close, как хотелось
бы, так как форма еще не создана и закрывать нечего.
Есть и другой способ - по списку загруженных приложений
procedure TForm1.FormCreate(Sender: TObject);
VAR
Wnd : hWnd;
buff : ARRAY[0.. 127] OF Char;
Begin
Wnd := GetWindow(Handle, gw_HWndFirst);
WHILE Wnd <> 0 DO BEGIN
IF (Wnd <> Application.Handle) AND (GetWindow(Wnd, gw_Owner) = 0)
THEN BEGIN
GetWindowText (Wnd, buff, sizeof (buff ));
IF StrPas (buff) = Application.Title THEN
BEGIN
MessageDlg('Приложение уже загружено', mtWarning, [mbOk], 0);
Halt;
END;
END;
Wnd := GetWindow (Wnd, gw_hWndNext);
END;
End;
Еще один интересный способ для Win32. Дело в том, что можно в памяти создавать
временные файлы. При перезагрузке они теряются, а так существуют. Кстати,
этот метод можно использовать и для обмена информацией между вашими приложениями.
Пример:
program Project1;
uses
Windows, // Обязательно
Forms,
Unit1 in 'Unit1.pas' {Form1};
{$R *.RES}
Const
MemFileSize = 1024;
MemFileName = 'one_inst_demo_memfile';
Var
MemHnd : HWND;
begin
{ Попытаемся создать файл в памяти }
MemHnd := CreateFileMapping(HWND($FFFFFFFF),
nil,
PAGE_READWRITE,
0,
MemFileSize,
MemFileName);
{ Если файл не существовал запускаем приложение }
if GetLastError<>ERROR_ALREADY_EXISTS then
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end;
CloseHandle(MemHnd);
end.
Часто при работе у пользователя может быть открыто 5-20 окон и сообщение
о том, что программа уже запущено приводит к тому, что он вынужден полчаса
искать ранее запущенную копию. Выход из положения - найдя копию программы
активировать ее, для чего в последнем примере перед HALT необходимо добавить
строку :
SetForegroundWindow(Wnd);
Например так: program Project0;
uses
Windows, // !!!
Forms,
Unit0 in 'Unit0.pas' {Form1};
var
Handle1 : LongInt;
Handle2 : LongInt;
{$R *.RES}
begin
Application.Initialize;
Handle1 := FindWindow('TForm1',nil);
if handle1 = 0 then
begin
Application.CreateForm(TForm1, Form1);
Application.Run;
end
else
begin
Handle2 := GetWindow(Handle1,GW_OWNER);
//Чтоб заметили
:)
ShowWindow(Handle2,SW_HIDE); ShowWindow(Handle2,SW_RESTORE);
SetForegroundWindow(Handle1); //
Активизируем
end;
end.
procedure TForm1.Button1Click(Sender: TObject);
var
si : Tstartupinfo;
p : Tprocessinformation;
begin
FillChar( Si, SizeOf( Si ) , 0 );
with Si do begin
cb := SizeOf( Si);
dwFlags := startf_UseShowWindow;
wShowWindow := 4;
end;
Application.Minimize;
Createprocess(nil,'notepad.exe',nil,nil,false,Create_default_error_mode,nil,nil,si,p);
Waitforsingleobject(p.hProcess,infinite);
Application.Restore;
end;
Имею тег Программа
должна выдавать в браузер изображение. Прочитать JPeg, указать ContentType=Image/jpeg
и выдать изображение в SaveToStream умею. Как сделать тоже самое для файлов
GIF, в особенности анимационных? Если можно просто перелить дисковый файл
(пусть он хоть трижды GIF) в Response CGI-програмы, то как это сделать?