|   | Vitalonic - исходники |   |
| главная >> исходники >> ответы на вопросы | последнее обновление 21.01.04 |
| Ссылки |   | Вопросы |   |
|
Написать мне письмо Гостевая книга |
Пожалуйста, учтите, что приводимый код написан под библиотеку KOL и, как правило, не может быть использован в стандартных программах Delphi (т.е. программ под VCL) без некоторой переделки (подробнее об этом на главной странице). Все ссылки на первоисточники по возможности сохранены.
|
| Ответы |
Покопавшись в интернете, понял, что лучше всего это делать с использованием библиотеки ShlObj, которая к тому же просит подключить еще и ActiveX (источник здесь, я только немного подредактировал эту функцию). Однако, эти две библиотеки не сильно увеличивают размер программы, потому привожу здесь саму процедуру, создающую ярлык в указанной папке.
uses ShlObj, ActiveX;
procedure CreateLnk(FilePath, Folder, ShortCut, Description: PChar);
var
ShellLink: IShellLink;
hRes: HRESULT;
PersistFile: IPersistFile;
const
IID_IPersistFile: TGUID = (
D1:$0000010B;D2:$0000;D3:$0000;D4:($C0,$00,$00,$00,$00,$00,$00,$46));
begin
CoInitialize(nil);
hRes := CoCreateInstance(CLSID_ShellLink, nil, CLSCTX_INPROC_SERVER,
IID_IShellLinkA, ShellLink);
if SUCCEEDED(hRes) then
begin
ShellLink.SetPath(FilePath);
ShellLink.SetDescription(Description);
hRes := ShellLink.QueryInterface(IID_IPersistFile, PersistFile);
if SUCCEEDED(hRes) then
begin
PersistFile.Save(PWideChar(WideString(string(Folder) + ShortCut)), True);
PersistFile := nil;
end;
ShellLink := nil;
end;
CoUninitialize;
end; |
Исходник программы, демонстрирующий все описанное, забирайте здесь
Полазив по реестру, можно найти эти ключи, общие для систем 98/2000/XP (за остальные не ручаюсь). Кусочек кода приведен здесь:
var Key:HKey;
Desktop_Location:string;
begin
Key:=RegKeyOpenRead(HKEY_CURRENT_USER, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders');
Desktop_Location:=RegKeyGetStr(Key,'Desktop');
RegKeyClose(Key);
end; |
Соответсвенно, для получения местонахождения папки "Пуск" нужно заменить одну строчку на эту:
Start_location:=RegKeyGetStr(Key,'Programs'); |
Этот вопрос из области написания инсталляторов, как и два предыдущих.
Сначала надо эти файлы в ресурс запихнуть. Делается это так: нужно создать файл с расширением *.rc, написать в нем что-то типа:
NAME1 RCDATA "FileName1"
NAME2 RCDATA "FileName2"
...
где NAME - то, как файл будет называться в ресурсе (с расширением!), а FileName1 - собственно сам файл
Потом нужно откомпилировать с помощью утилиты brc32.exe, которая лежит где-то в каталоге Delphi, выполнив команду
>brc32.exe Имя_файла.rc
Если все прошло удачно, на диске появится файл Имя_файла.res, который собственно и нужно прописать в ресурсе (идем Project|View Source и делаем там такую строчку)
{$R Имя_файла.res}
Осталось только написать кусок программы, который будет это вытаскивать из ресурса.
Var MyStream:PStream; begin MyStream := NewWriteFileStream(GetStartDir+'FileName1'); Resource2Stream(PicStream,HInstance,'Name1',RT_RCDATA); MyStream.free; end; |
В приведенном примере первый файл помещается в папку, из которой запущена программа. Аналогично можно вытянуть второй и последующие файлы.
Однако, чтобы не увеличивать зря размер программы, гораздо интереснее файлы сначала упаковать, воспользовавшись библиотечкой типа ZLib, а потом распаковать при записи на диск. В этом случае в ресурс нужно помещать уже запакованные файлы. Сама процедура распаковки потребует некоторых усложнений:
uses KOLZLib;
function StreamCopy (Dest, Source: PStream; Count: DWord): DWord;
const
MAXBUFSIZE = $80000;
var
BufSize: DWord;
Readed: DWord;
Buffer: PChar;
Need: DWord;
begin
If Count=0 then begin
Source.Position:=0;
Count:=Source.Size;
end;
Result:=0;
If Count>MAXBUFSIZE then BufSize:=MAXBUFSIZE else BufSize:=Count;
GetMem(Buffer, BufSize);
try
repeat
If Count>BufSize then Need:=BufSize else Need:=Count;
Readed:=Source.Read (Buffer^, Need);
If Readed=STRM_ERROR then Exit;
If Dest.Write (Buffer^, Readed)=STRM_ERROR then Exit;
Dec(Count, Readed);
Inc (Result, Readed);
until (Count=0) or (Readed=0) or (Readed=STRM_ERROR);
finally
FreeMem(Buffer, BufSize);
end;
end;
procedure unpack(Dir:string);
const
STRM_ERROR = DWord (-1);
var
Source: PStream;
Dest: PStream;
Zipper: PStream;
Size: DWord;
begin
Source := NewMemoryStream;
Resource2Stream(Source,HInstance,'Name1',RT_RCDATA);
Source.Position:=0;
Dest:=NewWriteFileStream (Dir+'FileName1');
Source.Read(Size, 4);
NewZLibDStream (Zipper, Source, nil);
StreamCopy (Dest, Zipper, Size);
Zipper.Free;
Dest.Free;
Source.Free;
end; |
Здесь FileName1 - это имя уже распакованного файла, т.е. так, как он должен выглядеть на диске
Эту функцию я почти целиком списал с примера, который идет вместе с библиотекой KOLZlib, убрав только обработку исключений (если она нужна, можно легко ее вернуть).
Допустим, в редакторе типа Memo находится большой кусок текста, так что весь он не умещается в окне редактора и нужно пользоваться скролингом. А как программно прокрутить редактор к нужному месту? Придется немного повозиться с WindowsAPI:
Memo.Perform(WM_VSCROLL, Memo.Perform(EM_LINEFROMCHAR,symbol,0)*65536+SB_THUMBPOSITION,0); |
Здесь symbol - номер символа, к которому осуществляется прокрутка. В этом примере использованы две вложенные API-функции: внутренняя определяет строчку, в которой находится соответсвующий символ, а внешняя прокручивает редактор к этой строчке.
  наверх