Форум: "WinAPI";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.01.21;
Скачать: [xml.tar.bz2];




Вниз

Помогите найти ошибку 


Moscower   (2001-11-16 16:13) [0]

Видимо, конечно, в силу моей криворукости при программировании WinApi на Delphi возникают ошибки... :-( Подскажите пожалуйста, что я делаю не так?



program MVROrganizer;

uses
Windows, Dialogs, SysUtils, ole2auto,
Forms,
Tray in "Tray.pas" {Form1};

var fmhandle : HWND;
tekhandl : PChar;
temp : LongWord;
ptk, p1 : pointer;
outp : String;
lpMsgBuf : String;
{$R *.res}

begin

Application.Initialize;
tekhandl := PChar(IntToStr(Application.Handle)); // Находим хэндл главной формы приложения и запоминаем его в переменную tekhandl
fmhandle := CreateFileMapping(HWND($FFFFFFFF), nil, PAGE_READONLY, 0, sizeof(HWND), "Moscower"); // создаем карточный файл
if GetLastError<>ERROR_ALREADY_EXISTS then
begin
Application.CreateForm(TForm1, Form1);
if not WriteFile(fmHandle, ptk, sizeof(tekhandl), temp, nil) // пытаемся записать в него хэндл главной формы приложения
then
begin
// если ошибка
SetLength(lpMsgBuf, 256);
SetLength( lpMsgBuf, FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_FROM_SYSTEM,
nil,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
@lpMsgBuf[1],
255,
nil
));// то формируем сообщение о ней


MessageBox( Application.Handle, Pchar(lpMsgBuf), "GetLastError", MB_OK or MB_ICONINFORMATION ); // И выводим на экран
CloseHandle(fmhandle);

Application.Run;

end ;



end


end.



Код для обработки ошибки взял из SDK, видимо неудачно перевел его с C на Delphi...

Ошибки:

1. В карточный файл ничего не записывается и он идет на ошибку
2. Не могу получить сообщение об ошибке, вместо него показывается непереводимый набор символов.

Поправьте меня пожалуйста, как это нужно делать?



paul_shmakov   (2001-11-16 16:41) [1]

это вообще какой-то некоректный способ работы с файлами, проецируемыми в память. какая задача?
1. нужно создать объект-ядра "файл, проецируемый в память" (memory mapped file). создаеться он функцией CreateFileMapping. в первом ее параметре нужно передать дескриптор открытого файла или $FFFFFFFF, что говорит системе, что память под этот файл следует взять из страничного файла (или свопа по нашему). только не нужно это значение к HWND приводить, как в примере выше. если мы в этот файл что-то писать собрались, то нужно передать PAGE_READWRITE, а не PAGE_READONLY. размер файла указан верно. следует заметить, что если мы в первом параметре передали $FFFFFFFF, то не можем передать 0 вместо размера. если в первом параметре дескриптор на открытый файл, то можно передать 0 - файл целиком спроецируется.

2. спроецировать файл на адресное пространство процесса функцией MapViewOfFile. по тому значению, которое она вернет можно записать то, что нам нужно.

var
P: PChar;
begin
...
P := MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
StrCopy(P, "что-то, что нужно засунуть в файл");


3. вызвать UnmapViewOfFile и CloseHandle.



Moscower   (2001-11-16 17:42) [2]

СПАСИБО!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
РАБОТАЕТ!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


Прошу прощения за вот такой вопрос, просто увидел, у Ю. Зотова в примере cunnings на королевстве, как сделать так, чтобы программу можно было запустить только один раз. Вот я и решил доработать этот код с тем, чтобы в этот mapping file можно было записать handle процесса, а потом из программы, запущенной 2-ой раз прочитать его, и сделать активной форму с этим хэндлом. Но я абсолютно не знал, что это за mapping файл такой. Огромное спасибо, что разъяснили, как с ним работать!!!!!!!!!!!!!!!!!!!



paul_shmakov   (2001-11-16 23:07) [3]

сделать форму активной лучше не так. создаем, значит, файл, проецируемый в память, и тут видим, что он уже создан.
тогда делаем следующее: находим главное окно нашей программы с помощью FindWindow, посылаем в него какое-либо сообщение, нами определенное (например, WM_APP + 100).
в главное форме должен быть перехватчик-обработчик этого сообщения, который должен вызывать Application.BringToFront.
это самый нормальный способ.



Moscower   (2001-11-17 00:07) [4]

А чем это лучше, чем мой способ?



paul_shmakov   (2001-11-17 02:10) [5]

это сложнее и не особо нужно. хотя можно и вашим способом.
дело в другом. берем хэндл главного окна предыдущей копии (с помошью FindWindow или из файла считать). далее не нужно вызывать всякие ShowWindow(hwnd, SW_RESTORE), BringWindowToTop(hwnd), SetForegroundWindow и т.п.
а нужно послать в эту форму какое-то свое сообщение, которое она обрабатывая вызовет Application.BringToFront.
получается самый нормальный вариант (особенно, если куча модальных дочерних окошек открыта).



Raptor   (2001-11-17 10:29) [6]

Привет!

2paul_shmakov ©
Тут лучше использовать не файлы проэцируемые на память, а мютексы или атомы. Они есть объекты ядра и с 100% увереностью можна сказать, что два атома не не могут быть созданы одновременно. А с файлами есть возможность того, что они будут создаваться одновременно и Ваш метод не сработает.

Raptor.



paul_shmakov   (2001-11-18 15:54) [7]

2 Raptor:
проецируемый в память файл (memory mapped file) является 100%-ным объектом ядра наряду с мютексами, событиями, семафорами и т.д.



Raptor   (2001-11-18 21:42) [8]

Привет!

2paul_shmakov
Да, Вы правы. Извиняюсь.

2Moscower
Если Вас интересует проблема запуска только одной копии приложения советую почитать эту статью:
http://www.pgh.net/~newcomer/nomultiples.htm
или ее перевод:
http://www.rsdn.ru/article/?baseserv/avins.xml

Raptor.



Moscower   (2001-11-19 11:02) [9]

>Raptor
Спасибо, почитаю




Форум: "WinAPI";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.01.21;
Скачать: [xml.tar.bz2];




Наверх





Память: 0.74 MB
Время: 0.041 c
1-66237           Billy                 2002-01-02 02:52  2002.01.21  
все о IOResult


3-66207           borisich              2001-12-16 18:51  2002.01.21  
Какой лучше формат СУБД использовать для локальных


4-66411           Tatyana               2001-11-12 16:49  2002.01.21  
Как встроить свою кнопку (со своими действиями) в ToolBar Internet Explorer


1-66267           hacker                2002-01-01 21:48  2002.01.21  
Обработка событий в дмнамически создаваемых компонентах


14-66347          anod                  2001-11-25 00:12  2002.01.21  
?