[delphi] odświeżanie pulpitu

0

za pomocą

      DC := BeginPaint(GetDesktopListViewHandle, PS);
      SetBkMode(DC, TRANSPARENT);
      SetTextColor(DC, RGB(0, 0, 0));
      TextOut(DC, 1024 - 200, i, Pchar(s), Length(s));
      EndPaint(GetDesktopListViewHandle, PS);

pisze na pulpicie pewien napis..
po naciśnięciu przycisku zmienna "s" sie zmienia.
co należy dodać do procedury przycisku, aby po zmianie wartości, widok pulpitu odświeżył sie, tak aby było widać od razy nowy napis, gdyż zmienia się on dopiero po kliknięciu prawym przyciskiem na pulpit i kliknięciu "odśwież".
próbowałem używać 2 procedur, które były w faq, ale niestety odświeżają one pulpit, ale nie mój napis.
proszę o pomoc.

0

proponowal bym zastosowac funkcje InvalidateRect i odmalowac tylko ten fragment, ktory Ciebie interesuje.

0

no tak... a wiec mam:

    r.Left := 700;
    r.Top :=2;
    r.right := 1024;
    r.Bottom :=300;
    InvalidateRect(GetDesktopListViewHandle, r, false);

nie jestem pewien co do parametrów "r", w każdym razie interesuje mnie prostokąt u góry po prawej stronie. około 100/300, tak mniej więcej.

Moglbyś mi poradzić, jak powinna wyglądać ta funkcja ?

0

http://msdn2.microsoft.com/en-us/library/ms534893.aspx

InvalidateRect(GetDesktopListViewHandle,RECT(,,,),true)

oczywiscie jak po pulpicie rysujemy, bo jak jest jeszcz jakies okno to nie ...

0

więc mam:

    InvalidateRect(GetDesktopListViewHandle,rect(800, 10, 1024, 300),true)

i mam blad Incopatible Types "TRect" and "PRect".

dlatego wcześniej dałem zmienna r: Prect; ale też nie działało.

jakiś inny pomysł?

0

Przecież ta metoda oczekuje na wskaźnik... do struktury typu TRect, więc musisz przekazać wskaźnik, a nie całą strukturę.

0

ok, teraz mam kod :

r: Trect;

      r.Left := 700;
      r.Top := 1;
      r.right:=1024;
      r.Bottom:=300;
      InvalidateRect(GetDesktopListViewHandle,@r,true);

ale tekst zamiast się odświeżać, po prostu znika.

i w dalszym ciągu mam problem...z prawidłowym odświeżeniem.

0

i udało mi się :)
dałem:

    InvalidateRect(GetDesktopListViewHandle,@r,true);
    PostMessage(FindWindow('Mojprogram', nil), PAIN, 0, 0);

gdzie pain odpowiada za komunikat WM_PAINT w DLLce.

ale mam kolejny problem, po nacisnieciu przycisku tekst się elegancko odświeża, natomiast, w DLLce z HOOKIEM.....po jakim komunikacie wstawić to :

    InvalidateRect(GetDesktopListViewHandle,@r,true);
    PostMessage(FindWindow('Mojprogram', nil), PAIN, 0, 0);

aby po np. zminimalizowaniu okna, które zasłaniało napis, napis się odnowił (gdy jakies okno go przykryje znika), albo jakiś komunika, który by odświeżał napis co powiedzmy sekunde ? ( drugie pytanie, czy takie odświeżanie co sekunde tym sposobem nie byłoby zbyt pamięcio-żerne ?) ?

0

skoro juz robisz hooka to lap komunikaty odmalowywujace i w nich odmalowywuj (wm_paint wm_erasebk, wm_ncpaint ....).

0

hmm a moglbys mi podac stronke ze wszystkimi komunikatami odpowiadającymi za malowanie ? np. jak odsłoni sie pulpit ?

btw. hooka robie, ponieważ moje przyciski są tworzone na pulpicie, a musze jakoś wyłapywać czy zostały nacisniete :P

0

a wpisales do googli ktorekolwiek z nich ... pierwszy link, WM_NCPAINT i szczesliwy traf !

Painting and Drawing Messages
http://msdn2.microsoft.com/en-us/library/ms534875.aspx

BTW jak juz maja byc zmiany na forum to jestem za emotikonka w stylu rece opadaja, sciana mi nie do konca pasuje

0

hmm wpisałem w msdn'ie pierwsze 2...znalazłem opis tych komunikatów, ale tego spisu nie :)

w każdym razie dziękuję.

0

kurczę, mógłbyś mi powiedzieć, które komunikaty obsłużyć ? te wszystkie czy tylko niektóre ?

0

te powinny wystarczyc w 99.9%

WM_DISPLAYCHANGE
WM_ERASEBKGND
WM_ICONERASEBKGND
WM_NCPAINT
WM_PAINT
WM_PAINTICON

generalnie nawet nie musisz ich obslugiwac, ustaw hooka na po komunikacie i wtedy odmalowywuj

0

Podstawowe pytanie - po co w ogóle cokolwiek rysować po pulpicie? Wystarczy zrobić własne przezroczyste okno z rodzicem ustawionym jako pulpit i będzie wyglądało elegancko - można tak łatwo osiągnąć efekt jakiegoś OSD czy innego pulpitowego gadżetu.

0

Oczywiście wiem, że wystarczy zrobić przeźroczyste okno, ale postawiłem se zadanie zrobienia "normalnego" rysowania po pulpicie tekstu, który praktycznie nie znika tzn. jest cały czas, rysowania prawdziwego, a nie rysowania po oknie, które jest przeźroczyste :)

0

Hmmm. Więc teraz mam tak:
Program:

Const
  REFR = WM_USER + 105;

Case uMsg of
  REFR:
    begin
      InvalidateRect(GetDesktopListViewHandle,@r,true);
      PostMessage(FindWindow('Program', nil), PAIN, 0, 0);
    end;

DLL:

Const
  REFR = WM_USER + 105;

Function SysMsgProc(nCode: integer; wParam: WPARAM; lParam: LPARAM): lresult; stdcall;
begin
result := 0;
  pcws := PCWPSTRUCT(lparam);
  case pcws.message of
    WM_DISPLAYCHANGE:
      PostMessage(FindWindow('Program', nil), REFR, 0, 0);
    WM_ERASEBKGND:
      PostMessage(FindWindow('Program', nil), REFR, 0, 0);
    WM_ICONERASEBKGND:
      PostMessage(FindWindow('Program', nil), REFR, 0, 0);
    WM_NCPAINT:
      PostMessage(FindWindow('Program', nil), REFR, 0, 0);
    WM_PAINT:
      PostMessage(FindWindow('Program', nil), REFR, 0, 0);
    WM_PAINTICON:
      PostMessage(FindWindow('Program', nil), REFR, 0, 0);
{..dalszy ciąg funkcji, obsługa przycisków..}

i mój napis odświeża się, ale praktycznie cały czas się odświeża (tzn. szybko miga).

Już naprawdę nie wiem, co zrobić aby odświeżał się "normalnie" wtedy kiedy trzeba.

0

Skoro malujesz tylko i wylacznie po SysListView to lap wiadomosci tylko i wylacznie od tego okna a nie od wszytskich, mozesz jeszcze sprawdzac czy nie ma ustawionego obszaru migania.

Pytanie co chcesz osiagnac ?? Czy ma to zamolowywac ikony na pulpicie ?

a i jeszcze mi sie przypomnialo, aby dzialalo tez z aktywnym pulpitem

function GetDesktopListViewHandle: THandle;
var
   S: String;
   re:thandle;
begin
  Result := FindWindow('ProgMan', nil);
  Result := GetWindow(Result, GW_CHILD);
  Re := FindWindowEx(Result, 0, 'Internet Explorer_Server', nil);
  if re <> 0 then
  begin
   Result := re;
   exit;
  end;

  Result := GetWindow(Result, GW_CHILD);
  SetLength(S, 40);
  GetClassName(Result, PChar(S), 39);
  if PChar(S) <> 'SysListView32' then Result := 0;
end;
0

a mógłbyś mi poradzić jak wyłapywać tylko komunikaty do SysListView ?

Hmm a mój program działa tak ( chcę osiągnąć) :
Na pulpicie rysuje plan lekcji ( zrobione )
Na pulpicie dodaje 2 przyciski : dalej i wstecz, które zmieniają wyświetlany dzień. ( zrobione )
I pozostało mi zrobienie tego, aby po zakryciu np. jakimś otwartym folderem napisu, on automatycznie sie odnowił.

Wszystko inne na pulpicie ma być normalnie.

0

w strukturze CWPSTRUCT masz tez uchwyt okna do ktorego jest komunikat, zatem na starcie zapisujesz w uchwyt okna (pamiec wspoldzielona) nastepnie porownujesz uchwyt czy to ten, jesli tak sprawdzasz komunikaty.

Swoja droga mozna to zrobic (plan lekcj)

  1. Kontrolka aktive X i polzyc ja na pulpit aktywny (zagniezdzona w html'u)

  2. Tworzymy okno i umieszczamy je jako dziecko pulpitu (+przezroczystosc)

0

Hmmm no tak, mogę tak zrobić, ale jak już wcześniej wspomniałem chcę zrobić program, który działa właśnie w ten sposób (wydaje się dosyć trudny, a najlepiej się uczy na rzeczach trudnych).

Hmmm doszedłem do czegoś takiego:

  case pcws.message of
    WM_DISPLAYCHANGE:
      If pcws.hwnd = GetDesktopListViewHandle then
        PostMessage(FindWindow('Gasior', nil), REFR, 0, 0);

i tak dalej dla reszty tych komunikatów, ale efekt dalej ten sam, napis miga, po kilkakrotnym naciśnięciu RMB na pulpicie i "odśwież" napis zaczyna migać, potem przestaje ale część ikon znika, jednym słowem coś się sypie.

z tego co rozumiem, z mojego kodu wynika:
że jeżeli hook przechwyci dany komunikat, sprawdza czy dochodzi on do uchwytu pulpitu, jeśli tak to odświeża?
czy może coś źle rozumiem ?
Bo już naprawdę nie wiem co jest nie tak.

0

Straszna kolejnosc i bajzel !

  1. sprawdz uchwyt (nie poszukuj za kazdym razem !!!)
  2. sprawdz komunikat
  3. nie wysylaj kolejnego a tylko odmaluj co ma byc ! (jakas malo zrozumiana siec komunikatow) - bez invalidate rect ! bo on znow wysyla komunikat .... (ewentualni oznacz jakos swoj komunikat - bo tak wpadasz w petle)
0

więc teraz mam:

  If pcws.hwnd = GetDesktopListViewHandle then
  case pcws.message of
    WM_DISPLAYCHANGE:
        PostMessage(FindWindow('Gasior', nil), REFR, 0, 0);
    WM_ERASEBKGND:
        PostMessage(FindWindow('Gasior', nil), REFR, 0, 0);
    WM_ICONERASEBKGND:   [........] i tak dalej

ale z tego co rozumiem, błąd polega na tym, że po przechwyceniu tych komunikatów, mój program wysyła je znowu, i tak w kółko ? jednym słowem się zapętla ?
jak przefiltrować komunikaty tak, aby po odebraniu komunikatu, który wysyła mój program, dll'ka go zignorowała ?

0

Jesli wylapiesz, ze cos zabrudzi twoje okno to:

  1. wysylasz komunikaty za pomoca invalidaterect (jesli chcesz sam odmalowac okno)
  2. to powoduje, ze okno sie odmalowywuje
  3. lapiesz komunikat i malujesz (bez invalidate rect)
0

wiec tak...

  1. jak wyłapie, że coś zabrudzi moje okno (te komunikaty: WM_PAINT itp. )
  2. wysyła do programu komunikat, program odmalowuje ( InvalidateRect )
    i teraz o co chodzi z tym
    "3) lapiesz komunikat i malujesz (bez invalidate rect) "
    bo nie bardzo rozumiem o co chodzi ?
0

moze odpowiem dlaczego sie zapetla

  1. lapiesz wm_paint
  2. wysylasz wiadomosc do programu
  3. w programie robiszz invalidaterect (tu rozbijamy sie na dwa)

4a)invalidaterect wysyla wm_paint, wm_erasebk do pulpity | 4b)Twoj program odmalowywuje pulpit
4b) ladujesz w 1) |

Zatem: gdy ty chcesz zmienic tekst to wysylasz TYLKO invalidaterect w przeciwnym razie system sam poprosi o odmalowanie.

w hooko obsluga wm_paint i domalowywujesz swoj fragment (mozesz ta procedure umiescic od razu w dll'ce).

0

Tylko problem polega na tym, że jak mam w programie po odebraniu komunikatu "REFR", (czyli tego, który wysyła DLL po przechwyceniu tych kilku komunikatów)
samo

      InvalidateRect(GetDesktopListViewHandle,@r,true);

to napis się nie odświeża, odświeża się dopiero jak mam :

      InvalidateRect(GetDesktopListViewHandle,@r,true);
      PostMessage(FindWindow('Gasior', nil), PAIN, 0, 0);

ale wtedy się zapętla...

0

Wklej kod biblioteki i programu okrojony tylko do malowania napisy. OKROJONY !!! Prosze !
Zobaczymy co z tego da sie zrobic.

0

Kod DLL'ki:

library GasiorHook;

uses
  Windows,
  Messages,
  Sysutils;

var
  Hok : hhook;
  pcws: PCWPSTRUCT;

const
  WLEWO = WM_USER + 101;
  WPRAWO = WM_USER + 102;
  PAIN = WM_USER + 130;
  REFR = WM_USER + 105;

function GetDesktopListViewHandle: THandle;
var
  S: String;
begin
      Result := FindWindow('ProgMan', nil);
      Result := GetWindow(Result, GW_CHILD);
      Result := GetWindow(Result, GW_CHILD);
      SetLength(S, 40);
      GetClassName(Result, PChar(S), 39);
      if PChar(S) <> 'SysListView32' then
      Result := 0;
end;

Function SysMsgProc(nCode: integer; wParam: WPARAM; lParam: LPARAM): lresult; stdcall;
begin
result := 0;
  pcws := PCWPSTRUCT(lparam);
  If pcws.hwnd = GetDesktopListViewHandle then
  case pcws.message of
    WM_DISPLAYCHANGE:
        PostMessage(FindWindow('Gasior', nil), REFR, 0, 0);
    WM_ERASEBKGND:
        PostMessage(FindWindow('Gasior', nil), REFR, 0, 0);
    WM_ICONERASEBKGND:
        PostMessage(FindWindow('Gasior', nil), REFR, 0, 0);
    WM_NCPAINT:
        PostMessage(FindWindow('Gasior', nil), REFR, 0, 0);
    WM_PAINT:
        PostMessage(FindWindow('Gasior', nil), REFR, 0, 0);
    WM_PAINTICON:
        PostMessage(FindWindow('Gasior', nil), REFR, 0, 0);
    WM_COMMAND:
      begin
        if HIWORD(pcws.wParam) = BN_CLICKED then
          case LOWORD(pcws.wParam) of
          99: PostMessage(FindWindow('Gasior', nil), WPRAWO, 0, 0); //przyciski
          100: PostMessage(FindWindow('Gasior', nil), WLEWO, 0, 0);
          end;
  end else
  Result := CallNextHookEx(Hok, nCode, wParam, lParam);
  end;
end;

Procedure SetHook; stdcall;
begin
  Hok := SetWindowsHookEx(WH_CALLWNDPROC, @SysMsgProc, Hinstance, 0);
end;

procedure Uninstallhook; stdcall;
begin
 if hok <> 0 then UnhookWindowsHookEx(hok);
end;

exports
  SetHook,
  Uninstallhook;

begin
end.

i funkcja WndProc w programie ( nie cała) :

  REFR:
    begin
      InvalidateRect(GetDesktopListViewHandle,@r,true);
    end;
  WLEWO:
    begin
      if dzien = 0 then dzien:=4 else
      if dzien <> 0 then dzien := dzien -1;
      InvalidateRect(GetDesktopListViewHandle,@r,true);
      PostMessage(FindWindow('Gasior', nil), PAIN, 0, 0);
    end;
  WPRAWO:
    begin
      if dzien = 4 then dzien:=0 else
      if dzien <> 4 then dzien := dzien +1;
      InvalidateRect(GetDesktopListViewHandle,@r,true);
      PostMessage(FindWindow('Gasior', nil), PAIN, 0, 0);
    end;
  PAIN:
    begin
      DC := BeginPaint(GetDesktopListViewHandle, PS);
      SetBkMode(DC, TRANSPARENT);
      SetTextColor(DC, RGB(0, 0, 0));
      case dzien of
      0:
        begin
          i:=1;
          AssignFile(tf, 'plan/pn.pln');
          Reset(tf);
          While not eof(tf) do
            begin
            Readln(tf, s);
            i:= i +17;
            TextOut(DC, 1024 - 200, i, Pchar(s), Length(s));
            end;
          CloseFile(tf);
        end;
      1: begin
          i:=1;
          AssignFile(tf, 'plan/wt.pln');
          Reset(tf);
          While not eof(tf) do
            begin
            Readln(tf, s);
            i:= i +17;
            TextOut(DC, 1024 - 200, i, Pchar(s), Length(s));
            end;
          CloseFile(tf);
        end;
      2: begin
          i:=1;
          AssignFile(tf, 'plan/sr.pln');
          Reset(tf);
          While not eof(tf) do
            begin
            Readln(tf, s);
            i:= i +17;
            TextOut(DC, 1024 - 200, i, Pchar(s), Length(s));
            end;
          CloseFile(tf);
        end;
      3: begin
          i:=1;
          AssignFile(tf, 'plan/cz.pln');
          Reset(tf);
          While not eof(tf) do
            begin
            Readln(tf, s);
            i:= i +17;
            TextOut(DC, 1024 - 200, i, Pchar(s), Length(s));
            end;
          CloseFile(tf);
        end;
      4: begin
          i:=1;
          AssignFile(tf, 'plan/pt.pln');
          Reset(tf);
          While not eof(tf) do
            begin
            Readln(tf, s);
            i:= i +17;
            TextOut(DC, 1024 - 200, i, Pchar(s), Length(s));
            end;
          CloseFile(tf);
        end;
      end;
      EndPaint(GetDesktopListViewHandle, PS);
    end;
0

czyli nie robisz jak powiedzialem. Jak dostajesz komunikat wm_paint masz odmalowac okono (PAIN) a nie odswierzyc (REFR) bo wtedy wpadasz w petle.

Odswierzasz - invalidate rect -> tylko jak TY(twoj program) cos zmienisza
w przeciwnym przypadku system sam sie o to zatroszczy.

a poza tym jest to bylejaki kod (zreszta sie tego spodziewalem)
PROSZE poczytaj !!!
Jak założyć globalnego hooka

w przypadku hookow robienie czegos bylejak skonczy sie zwiecha system (szczegolnie tak niskopoziomowego)

Druga sprawa, pisalem abys lapal komunikaty PO !
czyli WH_CALLWNDPROCRET, bo jak lapiesz przed to jest szansa, ze zamaluje okno orginalne.

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