Возникла проблема: Hеобходимо вызывать функцию, которая находится в 16-битной dll из 32-битного приложения.

const
  Gfsr_SystemResources = 0;
  Gfsr_GdiResources = 1;
  Gfsr_UserResources = 2;
var
  hInst16: THandle;
  GFSR: Pointer;
{ Undocumented Kernel32 calls. }
function LoadLibrary16(LibraryName: PChar): THandle; stdcall; external
kernel32 index 35;
procedure FreeLibrary16(HInstance: THandle); stdcall; external kernel32
index 36;
function GetProcAddress16(Hinstance: THandle; ProcName: PChar): Pointer;
stdcall; external kernel32 index 37;
procedure QT_Thunk; cdecl; external kernel32 name 'QT_Thunk';
{ QT_Thunk needs a stack frame. }
{$StackFrames On}
{ Thunking call to 16-bit USER.EXE. The ThunkTrash argument
  allocates space on the stack for QT_Thunk. }
function NewGetFreeSystemResources(SysResource: Word): Word;
var
  ThunkTrash: array[0..$20] of Word;
begin
  { Prevent the optimizer from getting rid of ThunkTrash. }
  ThunkTrash[0] := hInst16;
  hInst16 := LoadLibrary16('user.exe');
  if hInst16 < 32 then
    raise Exception.Create('Can''t load USER.EXE!');
  { Decrement the usage count. This doesn't really free the
    library, since USER.EXE is always loaded. }
  FreeLibrary16(hInst16);
  { Get the function pointer for the 16-bit function in USER.EXE. }
  GFSR := GetProcAddress16(hInst16, 'GetFreeSystemResources');
  if GFSR = nil then
    raise Exception.Create('Can''t get address of GetFreeSystemResources!');
  { Thunk down to USER.EXE. }
  asm
    push SysResource  { push arguments }
    mov edx, GFSR     { load 16-bit procedure pointer }
    call QT_Thunk     { call thunk }
    mov Result, ax    { save the result }
  end;
end;

(Автор - Quality freeware from Sight&Sound, Slovenia :
http://www.sight-sound.si/ )

 "CPL-щина"
Файл примера можно скачать здесь
Уважаемые любители нетрадиционного использования Delphi 4 вашему вниманию предлагается поразмять мозги, руки, ноги, другие части тела (по вкусу).
____________________________________________________________________________

    Итак главная новость сезона - cpl - это на самом деле DLL. Поэтому, приступая к работе создайте пустой проект DLL (по настоящему отвязные   программеры могут сваять ActiveX DLL - это привнесет приятное разнообразие в работу и создаст небольшую кучку проблем, впрочем легко разрешимых- но зато вы сможете управлять вашей cpl извне, правда зачем это нужно не знаю).

    Момент номер два, вам позарез нужен файл ресурсов (с таким же названием как и   название библиотеки DLL- по умолчанию это название проекта)-в противном случае ваша cpl- так никогда и не появиться в панельке управления.   Для написания файла ресурсов (*.res) необходим какой нибудь редактор ресурсов, в крайнем случае сойдет и ImageEditor из стандартной поставки Дельфей. Вы, мужественно сжав мышь в руке, постарайтесь сваять иконку с названием MAINICON и запихнуть ее в файл ресурсов с таким же названием как и ваша DLL.

    Момент номер три. Файл DLL должен ОБЯЗАТЕЛЬНО экспортировать функцию с именем CPlApplet (не cplApplet и не как то иначе ТОЛЬКО так)-иначе панель  управления не сможет инициализировать вашу cpl-и даже хуже, как выяснилось, при открытии панельки управления Windows КАЖДЫЙ РАЗ просматривает каталог ...\System (либо ...\System32) в поисках cpl-ок и посылает им запросы через  эту эспортируемую функцию. Т.е. если у вас имя функции отличается может  произойти полное зависание системы при открытии панели управлени (лечиться Reset). Кстати можно экпортировать и другие функции (кстати так делают Screen Saver'ы)- это не возбраняется.

    При эспорте функции используйте прототип функции находящийся в файле cpl.pas
вида
function CPlApplet(hwndCPl: THandle; uMsg: DWORD;lParam1, lParam2: Longint): Longint;export;stdcall;


    Вот и все что я хотел бы сообщить об увлекательном занятии русских программистов: попытках заставить систему программирования БАЗ ДАННЫХ выполнять черт знает, что-но я тоже люблю этим заниматься ;-).

P.S. Учите C++ так как подобные штуки легонько на нем пишуться. Да и я портировал этот пример из MSDN от Visual C++ 6.0

P.P.S. В тексте программы вы наткнетесь на фукцию Form.Create в которой вызывается  ShowWindowsAsync (данная кривость используется, чтобы не показывалось окошко на таск баре). В ФИДО ходило много материалов на эту тему но здесь (в Дельфи)
Params.ExStyle:=Params.ExStyle and ( not WS_EX_APPWINDOW); в CreateParams
не работает, поэтому ногами не бить  (сейчас тружусь на проблемкой - работаю с SH_-объектами )
тех кого сей трабл не устраивает могут спокойно ее выбросить

1.Установка. Проста до ужаса. Необходимо записать файл cpl в
каталог Windows\System (Win95) либо WindowsNT\System32 (WinNT)
после этого ОБЯЗАТЕЛЬНО (особенно для NT) перезагрузить компьютер
можно в софт-режиме (т.е не полность а с Shift-ом, но это в мастдайке'95).
2. Програмулька отлаживалась и разрабатывалась на Delphi 4 (sp3,sp4) так, что
если не будет работать у вас проверьте наличие необходимых сервис-паков
(хотя по идее, должно работать везде, даже по D3.02)-не будет чего
работать - пишите.
3. В дельфях в каталоге Source\RTL\Win усть библиотека cpl.pas проверьте,
чтобы она у вас была.
4. Программа проверялась на корректность работы под Windows 95, Windows 98
WindowsNT (Workststion +Server)- глюков нет, если у вас получиться заглючить
программу- пишите, мне будет интересно.
5. Ссылки на авторство не обязательны но желательны (я тоже не за час ее написал)
6. В качестве нагрузки могу выслать аналогичные примеры написания cpl
выдернутые из MSDN (там два примера общим тоннажем в ~100 КВ)-возможно
это заинтересует любителей C++Builder

P.S. ну вот и все, что касается такой интересной феньки как cpl.

28 июля 1999 года                 Спорик Алексей Евгеньевич

main_back.gif (3425 bytes)

Используются технологии uCoz