Форум: "WinAPI";
Текущий архив: 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
Спасибо, почитаю
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2002.01.21;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.004 c