Problem z przesyłaniem String'u przy pomocy SendMessage

0

Mam takie cos

program Editor;

uses
  Forms,
  Windows,
  Messages,
  Dialogs,
  SysUtils,
  Unit1 in 'Unit1.pas' {BodyMultiEdytor},
  Unit2 in 'Unit2.pas' {Debugger},
  dlgConfirmReplace in 'dlgConfirmReplace.pas' {ConfirmReplaceDialog},
  dlgReplaceText in 'dlgReplaceText.pas',
  dlgSearchText in 'dlgSearchText.pas' {TextSearchDialog},
  AppLib in 'AppLib.pas';

CONST
 HEAD_APP_CLASS = 'TBodyMultiEdytor';

var
  TMPHandle  : HWND;
  I       : Integer;
{$R *.res}

procedure WriteMessage(Data:String);
var   Handle  : HWND;
begin
  Handle:=FindWindow(HEAD_APP_CLASS,nil);
  SendMessage(Handle,WM_USER + 6001,6001,DWord(PChar(Data)));
end;

begin
  TMPHandle:=FindWindow(HEAD_APP_CLASS,nil);
  if (ParamStr(1) <> '') AND (TMPHandle <> 0) then begin
    for I := 1 to ParamCount do WriteMessage(ParamStr(I));
    Exit;
  end;

  Application.Initialize;
  Application.Title := 'Multi Edytor';
  Application.CreateForm(TBodyMultiEdytor, BodyMultiEdytor);
  Application.CreateForm(TDebugger, Debugger);
  Application.CreateForm(TConfirmReplaceDialog, ConfirmReplaceDialog);
  //Debugger.Show;
  Application.Run;
end.

jak się mój program uruchamia to sprawdza czy jest kopia jego jak jest to wysyła parametry z jakimi została uruchomiona i teraz tak jak uruchamiam to zamiast przekazywać ścieżkę to czasem wrzuca jakieś znaczki ale częściej jest puste (WriteMessage(ParamStr(I));) ale jak użyje tego tak WriteMessage('@WTF!); to poprawnie wysyła tą wiadomość nie wiem czemu...

  private
    procedure EventGetMessage(var Msg: TMessage); message WM_USER + 6001;

...

procedure TBodyMultiEdytor.EventGetMessage(var Msg: TMessage);
var
 DataMsg: PChar;
begin
 DataMsg:=PChar(msg.lParam);
 Msg.Result:=1;
 if Msg.WParam = 6001 then ShowMessage(DataMsg);// CreateTabEdit(DataMsg);
end;
0

ale to nie tłumaczy czemu nie działa mi to ...

0

to nie ma sensu ale dobra ...

0

sam nie masz sensu. Co więcej nie masz też wiedzy ani umiejętności. I na koniec nie masz też nawet na tyle przyzwoitości i chęci żeby najpierw zobaczyć czy coś działa czy nie.

0

to czemu nie wysyła normalnie stringu z ParamStr(I) ale zwykły 'jakis text' działa poprawni ?

0

Mnie osobiście dziwi ten kawałek kodu (sformatowany po mojemu...):

if (ParamStr(1) <> '') and (TMPHandle <> 0) then
  begin
    for I := 1 to ParamCount do
      WriteMessage(ParamStr(I));

    Exit;
  end;

Skąd wiesz, że ParamStr(1) zawsze istnieje? Być może dlatego dostajesz śmieci, bo taki parametr nie istnieje, a Ty się do niego odwołujesz (dziwne, że debuger nie reaguje);

Najpierw sprawdź, czy faktycznie drugi parametr istnieje, a później go wykorzystaj;


Jeśli to dalej nie pomogło - użyj debuger'a i krok po kroku sprawdzaj stan zmiennych;

0
Furious Programming napisał(a)

Najpierw sprawdź, czy faktycznie drugi parametr istnieje, a później go wykorzystaj

to "if ParamStr(1) <> '' " nie wystarcza d sprawdzenia tego?

0

to "if ParamStr(1) <> '' " nie wystarcza d sprawdzenia tego?

Niestety nie;

To tak, jakbyś miał macierz o długości 1 (Length(aTab) = 1) a odwoływałbyś się do aTab[1], co jest niepoprawne, bo ten element nie istnieje (w przypadku macierzy dynamicznych);

Do sprawdzenia ilości parametrów masz funkcję ParamCount, która zwróci 1, jeśli program uruchomiłeś bez żadnego parametru, a jeśli otworzyłeś jeden plik spowinowacony z Twoim programem - zwróci 2; Więc przed warunkiem sparwdzającym wartość drugiego parametru sprawdź najpierw czy taki istnieje;


Poza tym parametry tak jak i wszystko w programowaniu indeskuje się od 0, nie od 1!

0

mylisz się bo ParamCount zwraca ilość parametrów nie licząc pierwszego ParamStr(0) albo inaczej Application.Exename
czyli jeżeli istnieje ParamStr(1) to ParamCount zwróci 1 dlatego jest for I := 1 to ParamCount do bez -1 przy ParamCount
dla testu
if (ParamCount > 0) AND (TMPHandle <> 0) then begin
for I := 1 to ParamCount do begin
ShowMessage(ParamStr(I));
WriteMessage(ParamStr(I));
end;
Ścieszkę wyświetli w msgboxie
ale aplikacja odbierze to i ma wyświetlić
DataMsg:=PChar(msg.lParam);
Msg.Result:=1;
ShowMessage(DataMsg);
i zwraca albo puste albo krzaki albo wywala błąd
First chance exception at $7651B727. Exception class EAccessViolation with message 'Access violation at address 00405457 in module 'Editor.exe'. Read of address 01F1CCA8'. Process Editor.exe (3420)

PS @furious programming
String to nic innego jak tablica typu Char, więc indexujesz ją od 0 czyli jak długość Stringu ma 1 to odwołujesz się do indexu 0 jak masz długość 6 to by odwołać się do ostatniego elementu dajesz index 5...
co do ParamStr(1) <> '' " wystarczy to bo jeżeli nie ma ścieżki (jest ona pusta) to poco cokolwiek robić dalej
np
var s:String;
begin
s:='';
if s <> '' then ShowMessage('jednak coś jest');

0

Fakt, nie liczy pierwszego; Mimo wszystko często dostajesz AV, stąd można wywnioskować, że odwołujesz się do elementu, który nie istnieje;

Napisz sobie osobną aplikację i przetestuj kod; Być może nie tutaj leży problem; Poza tym użyj debuger'a i prześledź pokolei odpowiednie zmienne;


proqix napisał(a)

String to nic innego jak tablica typu Char, więc indexujesz ją od 0 czyli jak długość Stringu ma 1 to odwołujesz się do indexu 0 jak masz długość 6 to by odwołać się do ostatniego elementu dajesz index 5...

Nigdy w życiu, String to nie jest alias dynamicznej tablicy typu Char, więc znaków nie indeksuje się od 0; Dla potwierdzenia masz prosty kod:

program StringMyth;

{$APPTYPE CONSOLE}

var
  sLine: String;
begin
  sLine := '123456';

  WriteLn('Line:   ', sLine);
  WriteLn('Length: ', Length(sLine));
  WriteLn;
  WriteLn('sLine[1]: ', sLine[1]);
  WriteLn('sLine[6]: ', sLine[6]);

  ReadLn;
end.

na wyjściu dostaję:

Line:   123456
Length: 6

sLine[1]: 1
sLine[6]: 6

więc to nie zwykła macierz; Jeśli podam taką linię w kodzie:

WriteLn('sLine[0]: ', sLine[0]);

dostanę błąd kompilatora: [Error] StringMyth.dpr(15): Element 0 inaccessible - use 'Length' or 'SetLength';

Poza tym podałeś nowy kod:

if (ParamCount > 0) AND (TMPHandle <> 0) then begin
    for I := 1 to ParamCount do begin
      ShowMessage(ParamStr(I));
      WriteMessage(ParamStr(I));
    end;

w którym nie umieściłeś sprawdzania zawartości parametru o indeksie 1; Powinieneś go dodać:

if (ParamCount > 0) then
  if (ParamStr(1) <> '') and (TMPHandle <> 0) then
    for I := 1 to ParamCount do
      begin
        ShowMessage(ParamStr(I));
        WriteMessage(ParamStr(I));
      end;
0

fakt pomyliłem się (to tak działa w Pawn'ie )

1 użytkowników online, w tym zalogowanych: 0, gości: 1