Komunikaty i Access Violation

0

Piszę notanik z zakładkami... I chcę zrobić coś takiego, że jak otwieram jakiś plik tekstowy moim notatnikiem, a już mam otwartą jego jedną kopię (notatnika), to żeby ten plik się otworzył w tej już istniejącej instancji, a ta druga zeby sie zamknela.

Mam kodzik:

(wyslanie komunikatu - w źrodle projektu)


const
WM_OPENFILE = WM_USER + 1000;

var
  hM : HDC;
  handle: THandle;
  buffer: string;

begin
  hM:=CreateFileMapping(THANDLE($FFFFFFFF),nil,
  PAGE_READONLY,0,32,'ApplicationTestMap');

  if GetLastError=ERROR_ALREADY_EXISTS then
  begin

    handle:= findwindow('TFrmMain', nil);

    if paramstr(1)<>'' then
    begin
    buffer:=paramstr(1);
    sendmessage(handle, WM_OPENFILE, integer(PChar(buffer)), 0);
    end;

    Application.Terminate;
    CloseHandle(hM);
  end;

(Odebranie komunikatu - w kodzie programu)


const
  WM_OPENFILE = WM_USER + 1000;

type
  TfrmMain = class(TForm)
    (...)
  private
    { Private declarations }
  public
    (...)
  procedure tworz_zakladke;
  procedure wmOpenFile(var msg: TMessage); message WM_OPENFILE;
    { Public declarations }
  end;

var
  frmMain: TfrmMain;
    (...)
  aktywnytab: integer;  // numer aktywnego tabu w pagecontrol


implementation

{$R *.dfm}

procedure TfrmMain.wmOpenFile(var msg: TMessage);
var
buffer: string;
begin
buffer:=string(msg.WParam);
tworz_zakladke;
TRichedit(findcomponent('rText'+inttostr(aktywnytab))).Lines.LoadFromFile(buffer);
end;

I przy uruchamianiu drugiej instancji (jeśli jest parametr, czyli otwarcie pliku) program wywala mi Access Violation w linii Sendmessage(...). Możliwe, że jest to spowodowane niepoprawnym formatem danych, czyli zamiana sciezki otwatego pliku na integer (zeby mozna bylo wyslac przez sendmessage jako parametr):

sendmessage(handle, WM_OPENFILE, integer(PChar(buffer)), 0);

Pomożcie! :)

0

sendmessage(handle, WM_OPENFILE, integer(PChar(buffer)), 0);

tak nie można przekazać bufora do innej aplikacji (przesyłasz offset adresu a segment masz tu ok, ale tam jest inny i ostatecznie wskazuje coś innego).
Może wysłać handle z GlobalAlloc lub przez dde, clipboard, albo WM_SETTEXT w jakimś ukrytym static tamtej aplikacji)

0

Hmm... Troche nie rozumiem ;)

Buffer to po prostu zwykly string...

0

zwykły string (chodzi o pchar, a nie string paskalowy, bo to zupełnie inny twór 8-O ),
to nie 4 bajty adresu, lecz blok pamięci zaczynający się pod tym adr.

możesz przekazywać go w kawałkach - po 4 znaki:
l := (strlen(buf)+1) shr 2; // div 4
for i := 0 to l-1 do SendMessage(wnd, WM_ptak, 0, LParam(buf+i*4)^); //

albo po 8: jeszcze 4 w wparam.

tamten odbiera i składa. :-D

0

Dobra, nie bede sie bawil w pisanie tych niezrozumialych dla mnie krzaczkow, zapisze sciezke pliku do otwarcia na dysku, wysle komunikat do poprzedniej kopii programu, zeby odczytala te sciezke i otworzyla ten plik i wszystko bedzie gralo :]. To chyba jakies nieporozumienie z tym wysylaniem stringa przez komunikaty...

Nigdy w zyciu nie wiedzialem np czegos takiego

FileMapping:= OpenFileMapping(FILE_MAP_WRITE, True, MemoryFileName);

albo

Move(PChar(t)^, ViewOfFile^, Length(t));

Hehehehe :D. Swoj rozwoj w delphi zatrzymam chyba wlasnie na wysylaniu stringa jako parametr komunikatu 😉

0

Po primo wysłanie komunikatu z jednej applikacji do drugiej pozwala wysyłać co tam ci się podoba ale to nie oznacza że tamta druga aplikacja ma do tego dostęp. Dwa procesy (twoja aplikacja i jej uruchomiona kopia) nie mają swobodnego dostępu do pamięci tej drugiej więc nie mżesz spbie wysłać tekstu który jest w twojej pamięci bo ta druga aplikacja nie ma do tej że pamięci dostępu.

W związku z tym ja pokazałem ci przykład z mutex'ami które normalnie służą do sunchronizacji ale i w tym przypadku spełniają swoją role. CreateMutex tworzy globalnie obiekt
OpenMutex (otwiera globalny obiekt jażeli istnieje)

jeżeli już istnieje(Mutex) to otwieramy sobie plik w pamięci OpenFileMapping (tworzony przez CreateFileMapping) i wykożystujemy funkcje MapViewOfFile która zwraca wskaźnik na pierwszą kmórkę pamięci pliku. UnmapViewOfFile zwalnia to ten wskaźnik no a CloseHandle zamyka uhwyt do tego pliku.

Owszem można wykorzystać zwykłe pliki no ale to działa zdecydowanie wolniej.

O jeszcze jedna uwaga apropos PostMessage(HWND_BROADCAST, WM_MESSAGE, 0, 0);
jeżeli używamy PostMessage z parametrem HWND_BROADCAST to WM_MESSAGE musi być zarejestrowane przez RegisterWindowMessage.

RegisterWindowMessage zwraca tę samą wartość dla tego samego parametru.

Mam nadzieję że to rozjaśnia sytuację

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