Форум: "WinAPI";
Текущий архив: 2002.10.21;
Скачать: [xml.tar.bz2];
ВнизHе могу найти ошибку Найти похожие ветки
← →
Aquaform (2002-09-08 16:29) [0]Где-то в коде ошибка. Где - не пойму.
Судя по всему это из-за Pchar"ов долбанных...
А точнее из-за неправильной работы функции wvsprintf
program Project1;
{$R *.RES}
uses
windows,
messages;
var
Instance: HWND;
WindowClass: TWNDClass;
Handle: HWND;
msg: TMsg;
procedure ExitProgram;
begin
Halt;
end;
//--------------------------------------------------------------
//САМОЕ ГЛАВНОЕ
//Функция обработки сообщений...
function WindowProc(Hwn,msg,wpr,lpr:longint):longint;stdcall;
var P1, P2, P3:Pchar;
x,y:integer;
begin
result:=defwindowproc(hwn,msg,wpr,lpr);
if msg=wm_destroy then ExitProgram;
if (msg=WM_LBUTTONUP) then //Если отпущена левая кнопка мыши
begin
new(P1); // Выделяется память под PChar"ы
new(P2);
new(P3);
try
P1:="x="; // P1= "x="
x:=loword(lpr); // x и y - координаты точки, где отпустили
y:=hiword(lpr); // кнопку мыши
wvsprintf(P2,"%i",@x); // P2= "35" - допустим
P1:=lStrCat(P1,P2); // P1= "x=35"
P1:=lStrCat(P1," y="); // P1= "x=35 y="
wvsprintf(P3,"%i",@y); // По идее, P3= "65" (например), но
// на самом деле P3 =" y=" (где-то так)
P1:=lStrCat(P1,P3); // Если б все было ок, то P1= "x=35 y=65"
messagebox(handle,P1,"Координаты курсора",mb_ok); //Сообщение о координатах
// Выводится на экран
finally
dispose(P1); // При вызове dispose происходит Run-Time Error
dispose(P2);
dispose(P3);
end;
end;
end;
//------------------------------------------------------------------
BEGIN
instance:=GetModuleHandle(nil);
Windowclass.style:=CS_HRedraw or CS_VRedraw;
WIndowClass.lpfnWndProc :=@WindowProc;
WindowClass.hInstance :=instance;
Windowclass.hbrBackground:=COLOR_BACKGROUND;
WindowClass.lpszClassName:="SCL";
Windowclass.hCursor :=LoadCursor(0,IDC_ARROW);
RegisterClass(WindowClass);
Handle:=CreateWindowEx(0,"SCL","Моя прога на WinApi",WS_SYSMENU or ws_maximizebox or WS_MINIMIZEBOX,(GetSystemMetrics(SM_CXSCREEN) div 2)-150,(GetSystemMetrics(SM_CYSCREEN) div 2)-150,300,300,0,0,instance,nil);
showwindow(handle,SW_SHOW);
while (GetMessage(msg,0,0,0)) do
begin
translatemessage(msg);
dispatchmessage(msg);
end;
end.
Ошибки обoзначены в комментариях к коду.
Может быть написал криво, но если вставить все это в Delphi и посмотреть на результат, думаю, все станет понятно.
Если кому влом разбираться, можно сделать так. Дайте мне исходник программы на winapi, с использованием только windows и messages. Чтобы создавалось окно, на него тыкаешь мышкой и всплывало сообщение, где написаны координаты точки куда ткнули мышкой вида "x=45 y=76"
Заранее спасибо.
← →
Anatoly Podgoretsky (2002-09-08 16:47) [1]По крайней мере ты не выделил память под PChar
← →
ZZ (2002-09-08 16:56) [2]Ошибки обoзначены в комментариях к коду.
Как в воду глядел :)
Что (и скока) ты хочешь получить после вызова
new(P1); // Выделяется память под PChar"ы
← →
Aquaform (2002-09-08 20:04) [3]Я пробовал и через Getmem, freemem.
А насчет new, dispose. Насколько я читал в функции new можно указать размер выделяемой памяти, а можно просто написать new(P1). Тогда для P1 выделится стандартный размер...
← →
Aquaform (2002-09-08 20:14) [4]А насчет new, dispose. Насколько я читал в функции new можно указать размер выделяемой памяти, а можно просто написать new(P1). Тогда для P1 выделится стандартный размер...
Это я ошибся.
Что (и скока) ты хочешь получить после вызова
new(P1); // Выделяется память под PChar"ы
Я рассчитываю, что после этого будет выполнено выделение памяти под данные на которые ссылается указатель и что указателю будет присвоен адрес начала выделенной памяти...
А как надо ?
← →
Ihor Osov'yak (2002-09-08 20:22) [5]2 Aquaform.
Вот когда сообразиш ответ на вопросы ZZ и Anatoly Podgoretsky - может и понятно станет ...
Подсказка - new(P1) выделяет столько памяти, сколько занимает структура, тип которой соотв. типизированому указателю. то есть для pchar будет sizeof(char) ....
В делфи программе (имхо) без особой надобности pchar юзать не надо, даже если работаем с апи). Это относится к твоему случаю.
Ты мог работать с обычними string, примерно так:
var s:string;
x,y:integer;
..
s := "x="+IntToStr(x)+" y="+IntToStr(y);
messagebox(handle,PChar(s),"Координаты курсора",mb_ok);
SetLen(s,0); { это необязательно, так как для string в даном случае относится к автоуничтожаемым элементам}
ЗЫ - Если очень любозхнателен - почитай как делфи работает со строками...
Зы2 Юзай phar если понимаешь, что делаешь
Зы3 Чтение с для неокрепших умов очень вредно
Зы4 И трижды вреден необдуманный перенос сишного "експириенса" в делфи
..
← →
Ihor Osov'yak (2002-09-08 20:26) [6]2 Aquaform.
Твой ответ на вропрос ZZ неверен. Но я очень надеюсь, что мой пред постинг тебе поможет разобратся. Разжевывание до конца в этом случае как то неприлично, ведь Вы все же на апи писать пытаетесь ...
← →
Aquaform (2002-09-08 23:51) [7]Вот в чем дело. String я использовать не могу. Так как заменять
wvsprintf(P2,"%i",@x);
надо чем то вроде
S2:=inttostr(x);
что я себе позволить не могу, так как модуль SysUtils не подключен.
Далее. Я переделал New, Dispose на GetMem, FreeMem - таже ситуация (Run-time error):
if (msg=WM_LBUTTONUP) then
begin
GetMem(P1,255);
GetMem(P2,255);
GetMem(P3,255);
try
P1:="x=";
x:=loword(lpr);
y:=hiword(lpr);
wvsprintf(P2,"%d",@x);
P1:=lStrCat(P1,P2);
P1:=lStrCat(P1," y=");
wvsprintf(P3,"%i",@y);
P1:=lStrCat(P1,P3);
messagebox(handle,P1,"Координаты курсора",mb_ok);
finally
FreeMem(P1);
Freemem(P2);
FreeMem(P3);
end;
end;
← →
Ihor Osov'yak (2002-09-09 01:18) [8]Мил человек, так подключи SysUtils. А если почему-то нет желания делать это, напиши что то типа
function IntToStr(aPrm:long):string;
var s:string;
begin
Str(aPrm,s);
result := s;
end;
и возврадуйся жизни ...
Далее:
GetMem(P1,255); - здесь все хорошо
P1:="x="; - а здесь мина. ибо поинтер смотрит уже не на запрошенную память, а на строку -константу длиной 2 байта
P1:=lStrCat(P1,P2); а злдесь возможен вылет, так как не известно что там у нас после двух байт константы
FreeMem(P1); - если перед тем не было вылета - то здесь точно - либо делаем попытку освободить память, которую не запрашивали -
напомина про P1:="x="; - сея вещь не копирует строку, а присвавает роинтеру P1 новое значение ...
... Я позволю себе быть не вежливым - мил человек, Вам не на апи программировать (во всяком случае пока), а книжки читать надо ...
← →
Ihor Osov'yak (2002-09-09 01:19) [9]поправка
вместо либо делаем попытку
должно ибо делаем попытку
← →
ggrisha (2002-09-09 09:49) [10]Ihor Osov"yak
нет там никакой мины
P1:="x="; не изменит указатель а запишет в выделенную область памяти значение.
Aquaform
Вообщето у меня этот пример с Getmem/Freemem на D6 вполне работает. Попробуй во Freemem непосредственно указать размер Freemem(P1,255); и т.д.
← →
Aquaform (2002-09-09 09:54) [11]Ihor Osov"yak, спасибо огромное ! Вы единственный, кто мне все внятно расстолковал. А книжки я читал, только про PChar"ы доступно и объемно нигде не нашел. Везде все на VCL
← →
ZZ (2002-09-09 10:18) [12]P1:="x="; не изменит указатель а запишет в выделенную область памяти значение
Да? Ты это сам проверял?
← →
ggrisha (2002-09-09 10:29) [13]ZZ
конечно проверял.
Достаточно сравнить адрес указателя до присваивания и после. Они совпадают.
← →
Ihor Osov'yak (2002-09-09 10:34) [14]2 ggrisha
А Вы уверены? Проверяли?
Подсказка: Сделайте просмотр pointer(P1) в режиме трассировки
до и после P1:="x="; ... А тогда и говорите.
2. Всякие шаманские действия (типа указывания 255) иногда и дают результат при одном - двум пробегам программы, хотя бы потому, что луна за вербу забежала... Но не надо делать скоропалительных выводов. Запустите фрагмент в цикле, так сотню раз ....
to Aquaform - согласен, довольно много книжек имеют уровень ... (нет, я лучше помолчу). Но в вашем случае достаточно было почитать внимательно хелп к GetMem и вспомнить, что PChar есть не более чем типизованый указатеть .... Согласен, в делфи вокруг
PChar много туману напущено, один из них - как PChar в режиме просмотра отображается (фактически мы пишем P1, а среда нам дает
к просмотру P1^ .... Поэтому и мой совет про pointer(P1)
ЗЫ - а Подгоретский и ZZ тебе тоже самое говорили, но как бы более концентрировано :-)
← →
Ihor Osov'yak (2002-09-09 10:40) [15]2 ggrisha -
> конечно проверял.
> Достаточно сравнить адрес указателя до присваивания и после.
> Они совпадают
Ну до чего человек же упрям. Не адрес указхателя сравнивать, а значение ... См мой пред постинг
Или сделай ShowMessage(IntToHex(integer(P1),8));
И призадумайся, почему P1 к интеджер приводится
← →
ZZ (2002-09-09 12:02) [16]ggrisha
procedure TForm1.Button1Click(Sender: TObject);
var
p : PChar;
begin
GetMem(p,255);
p:="f";
FreeMem(p);
end;
Запусти и проверь...
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2002.10.21;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.012 c