Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2002.10.21;
Скачать: CL | DM;

Вниз

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 вся ветка

Текущий архив: 2002.10.21;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.019 c
1-68711
Chlavik
2002-10-11 03:58
2002.10.21
Как перевести PHostEnt в String .......


14-68946
_Nicola_
2002-09-27 16:35
2002.10.21
Подкиньте компонент для ani GIF


3-68674
Lariska
2002-09-30 12:25
2002.10.21
BatchMove


7-69044
kosmach
2002-08-12 07:57
2002.10.21
TFileStream


14-68933
Дмитрий Сазонов
2002-09-27 00:23
2002.10.21
Перевод Си-программ в Паскаль