Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   Delphi | PChar into Cardinal (http://forum.oszone.net/showthread.php?t=43648)

Savant 11-01-2005 14:33 287555

Delphi | PChar into Cardinal
 
Чо-т голова совсем не варит... Как из PChar (или PAnsiChar) "сделать" тип Cardinal/Integer? Ну, к примеру, когда посылаешь сообщение WM_SETTEXT в lParam надо впихнуть указатель на строку, а в функции SendMessage lParam объявлен как Integer. Аналогично если действовать через TControl.Perform, то там lParam объявлен как Cardinal.

Netscaper 11-01-2005 15:30 287570

Код:

var A : Cardinal;
      S : String;
begin
  A := Cardinal(PChar(S));
end;


Savant 11-01-2005 15:34 287573

Netscaper
Ура! В Дельфи оказывается тоже есть преобразование типов как в Си. Ура, ура!
А почему я только щас об этом узнал?

Savant 11-01-2005 15:43 287574

Вложений: 1
Секундочку... Но если действовать так, то возникает Exception (в момент вызова Application.Run)
Код:

Form1.Controls[i*11].SetTextBuf(PChar(names[1,i+1]));
 
Form1.Controls[i*11].Perform(WM_SETTEXT,0,Cardinal(PChar(names[1,i+1])));

Эти 2 куска кода должны вести себя одинаково, так? Но если заменить первый вторым, то смотрим на скриншот.

Добавлено:
Цитата:

Цитата Delphi Help
EListError is raised when an error is made in a list, TStrings, or TStringList object.

Так у меня на форме нет списков и переменных TStrings тоже нет :confused:

Добавлено:
Тут еще подумал. А такой массив случайно не рассматривается в Делфи как TStrings^
Код:

a: array[1..n] of string;
Нееее... Это уж действительно бред пошел. Пора вздремнуть хоть часок

Netscaper 11-01-2005 16:46 287584

На рисунке сказано, что указанный индекс в списке выходит за пределы допустимых границ. Например, если на форме есть TListBox с 10 строчками, при обращении к 11 «вылезет» это исключение. Массив строк - не объект! Он не может рассматриватся как TStrings и т.п. Проверьте программу :)

Savant 11-01-2005 17:09 287595

заснуть не удалось...

Netscaper, я знаю, когда "вылезает" это исключение, но вот не могу понять где (встроенный дебаггер даже строку с исключением найти не может, точнее может, но это строчка Application.Run; ). Повторюсь, что
Цитата:

у меня на форме нет списков и переменных TStrings тоже нет
, но зато есть КУЧА Static Text (по-дельфийски Labels), некоторым из которых в определенный момент времени надо поменять "жирность" шрифта (про SetText я тут просто для примера написал). Вот со сменой этой жирности я и мучаюсь :). Что удивительно, у Form1.Controls[i] нет свойства TFont, которое есть у TControl, которым и является Form1.Controls[i]. Вот! Приходится через WinAPI выкручиваться, а там надо знать хендл конкретного контрола, который не знаю как найти, кроме функций поиска. Выкручиваемся соответственно через Form1.Controls[i].Perform(), но у него проблема с истолкованием PChar'a. Вот такая фигня...

Netscaper 11-01-2005 20:07 287640

Если хочешь, зашли в оркестр, посмотрю, а то что-то с твоих слов не очень ясно...

Savant 12-01-2005 23:41 288029

Netscaper, спасибо за хелпу, но с той проблемой (EListError) я уже рассчитался. Она происходила при вызове Form1.Controls[i] с несколько превышенным значением i. Соответственно заработали пребразования типов (я, кстати, нашел по ним наконец-то инфу в хелпе, в топике про округление дробных чисел :) ). Но никак не удается сменить жирность шрифта :(

Кстати, в чем я тут не прав?
Код:

procedure TForm1.EditxChange(Sender: TObject);
var
  a,b: Integer; s: String;
begin
//  ShowMessage(IntToStr(Sizeof(s)));  { !REMOVE! : debug info }
  Form1.Controls[Form1.ActiveControl.ComponentIndex].GetTextBuf(PChar(s), SizeOf(s)); { <-- ошибка EAccessViolation in 'user32.dll' }
  Val(s,a,b);
  if b<>0 then Form1.Controls[Form1.ActiveControl.ComponentIndex].SetTextBuf(PChar('0')) else
    if a>999999 then Form1.Controls[Form1.ActiveControl.ComponentIndex].SetTextBuf(PChar('999999'));
end;

В указанном месте возникает ошибка. Если эту строчку закомментировать и подставить какое-нибудь значение s, например s:='123', то все без проблем.

И еще: можно ли получить хендл контрола на форме, если известен его номер?

Netscaper 13-01-2005 19:32 288322

Savant
Цитата:

И еще: можно ли получить хендл контрола на форме, если известен его номер?
Можно. Если этот контрол есть твинконтрол :)
Помести на форму две кнопки:
Код:

procedure TForm1.Button2Click(Sender: TObject);
begin
  if (Form1.Controls[0] is TWinControl) then
    ShowMessage(IntToStr((Form1.Controls[0] as TWinControl).Handle));
  ShowMessage(IntToStr((Button1 as TWinControl).Handle));
end;

Если ошибка, значит, это - ошибка.
GetTextLen, GetTextBuf, Text Example - пример из Delphi Help
Код:

Этот пример копирует текст из поля редактирования в строку, заканчивающуюся нулем, а также кладёт строку в другое поле, когда пользователь кликает на кнопке формы.
procedure TForm1.Button1Click(Sender: TObject);

var
  Buffer: PChar;
  Size: Byte;
begin
  Size := Edit1.GetTextLen;      {Получить длину строки Edit1}
  Inc(Size);                      {Добавляем 1 для нуля}
  GetMem(Buffer, Size);          {Динамически создаем буфер}
  Edit1.GetTextBuf(Buffer,Size);  {Копируем в буфер}
  Edit2.Text := StrPas(Buffer);  {Конвертируем буфер в Паскалевскую строку Edit2}
  FreeMem(Buffer, Size);{ Освобождаем занятую память}
end;

Заметим, что такой же результат может быть получен проще:

procedure TForm1.Button1Click(Sender: TObject);

begin
  Edit2.Text := Edit1.Text;
end;


Savant 13-01-2005 21:56 288344

Netscaper, огромное спасибо за хелпу с получением текста, все отлично проворачивается.

Цитата:

Цитата Savent
можно ли получить хендл контрола на форме, если известен его номер?
Цитата:

Цитата Netscaper
Можно. Если этот контрол есть твинконтрол :)


К величайшему сожалению TLabel оказался производным от TGraphicControl. Зато вчитавшись в справку нашел кое-что полезное для себя:
Цитата:

Цитата Delphi Help
The TStaticText component functions like TLabel, except that it descends from TWinControl and therefore has a window handle. Use TStaticText instead of TLabel when the component’s accelerator key must belong to a windowed control — for example, on an ActiveX property page.

Самое важное выделил.

Savant 13-01-2005 22:49 288356

Netscaper
Можешь еще помочь? Как изменить порядок элементов в Form1.Controls[k] ? А то у меня с 0 по 4 идут TLabel, с 5 по 14 TImage, а потом снова продолжаются TLabel, но уже и вперемешку с TStaticText :biggrin: . И так я уже замучался сотню TLabel в TStaticText "переделывать", так тут еще фигня появилась. Пытался редактировать файл *.dfm, но он по-видимому не является определяющим в этом вопросе.

Netscaper 13-01-2005 23:27 288360

Не очень понял смысл использования свойства Form.Controls... Почему нельзя написать Form.Label1 или Form.StaticText?
Цитата:

Пытался редактировать файл *.dfm, но он по-видимому не является определяющим в этом вопросе.
Да, ты прав... Действительно, создается «от балды»... Влияет только на невизуальные компоненты, а на визуальные - нет. Порядок создания невизуальных можно менять в «Edit - Creation Order». Что, собственно, возвращает к вопросу о том, почему нельзя обращаться напрямую к Label или StaticText.

Savant 13-01-2005 23:40 288363

Netscaper
Цитата:

Не очень понял смысл использования свойства Form.Controls
У меня на форме МНОГО однотипных элементов всего четырёх "видов" (Label, StaticText, Edit, Image). Поэтому обращаться к ним ТАК
Код:

.........
Form1.Label1.Caption:="...";
Form1.Label2.Caption:="...";
...
Form1.Label20.Caption:="..";
.........

было бы не очень удобно и приятно.
Гораздо эффективнее так:
Код:

const a: array[1..20] of String = (...);
...........
for i:=0 to 19 do
  Form1.Controls[i].SetTextBuf(PChar(a[i+1]));

Аналогично мне надо одновременно сменить "жирность" шрифта у нескольких стоящий подряд StaticText. Так вот этого удобного порядка не получается, часть элементов у меня перемешались. А вот найти где этот порядок? Я по-моеему уже все перекопал, что в папке с моим проектом лежит... :(

Netscaper 14-01-2005 00:00 288372

Но ты можешь сделать так:
Код:

procedure TForm1.Button1Click(Sender: TObject);
var i : integer;
begin
  for i:=1 to 20 do
    (FindComponent('Label'+IntToStr(i)) as TLabel).Caption := IntToStr(i);
end;


Savant 14-01-2005 00:29 288384

Netscaper
Полностью согласен, я несколько ранее рассматривал различные варианты реализации нужного мне алгоритма, но по скорости выиграл Form1.Controls[k].SetTextBuf(PChar(a[k+1])); Не люблю перескакивать с одного на другое когда уже готово приличное кол-во кода, но видимо придется, раз нет возможности изменить порядок следования элементов в Form1.Controls[k].

Но вот для смены "жирности" шрифта он, кажется, мне подходит. Почему-то про него я забыл.


Время: 03:18.

Время: 03:18.
© OSzone.net 2001-