Ustawienie kolorów Edita i tworzenie okna modalnie przez CreateWindowEx.

0

Hej.

Zwykle radzę sobie sam, również w WinAPI. Ale tutaj potrzebna jest Wasza pomoc i przykłady kodu. Licze na userów @kAzek oraz @Azarien. Ale każda wskazówka jest cenna i mile widziana. Miejmy nadzieję, że tym razem zamiast mędrkować jak niektórzy z moim ostatnim problemem w PHP uda się Wam mi pomóc :)

Otóż dołączyłęm cały kod pisany pod Delphi 7, zależy mi aby powstała dllka byłą do końca w czystym WinAPI. Denerwowało mnie już ręczne zatrzymywanie pożądanych materiałów video pod preferowanym GOM Playerem aby spojrzeć pod klawiszem TAB jaki jest wyraźny aktualny czas stopklatki, wciskając klawisz TAB i zrobić po pauzie klawiszem Spacji zapis do pliku tekstowego aby później móc sobie wpisać czas pod Virtual Dubem aby na przykłąd coś wyciąć czy przyciąć. Postanowiłem ułatwić sobie ten proces, bo na rwórców playera bym nie liczył, bardzo wolno poprawiają bugi, a jeśli to już robią, tworzą niestety nowe i w dodatku olewają swoje włąsne forum suportu. A VLC nie bardzo mi odpowiada do oglądania rzeczy offline.

Dllka jaką stworzyłęm wykorzystuje znaną technikę spoofinku. Po to aby wykonać łatwo własny kod w ramach obcego procesu, a nie trzeba pisać osobnego loadera aby ją zainjectować Mianowicie mam problem z ogarnięciem docelowego okna, które pojawi się po wciśnięciu kombinacji Ctrl+S i pozwoli łątwo zarządzać ustalonymi pozycjami pliku video, a w przyszlości może sprzęgne to z VirtualDubem aby sobie ułąwić życie. Jednak o ile poniższy kod w programach WinAPI z oknami dialogowymi w zasobach z plików *.rc ustawia mi kolory bez problemów to tutaj nic się niestety nie dzieje. A nie mogę wygooglować lepszej metody. Poniżej wycinek najważniejszych fragmentów kodu.


type
  TColor = -$7FFFFFFF - 1..$7FFFFFFF;

const
  clLime = TColor($00FF00);
  clBlack = TColor($00000);

// ...

function ColorToRGB(Color : TColor) : Longint;
begin
  if Color < 0 then
  begin
    Result := GetSysColor(Color and $000000FF)
  end
  else
  begin
    Result := Color;
  end;
end;

function WndProc(AHWnd : HWND; Msg : UINT; AWParam : WPARAM; ALParam : LPARAM) : LRESULT; stdcall;
var
  DC : HDC;
  ThreadId : Cardinal;
  ControlKeyDown : boolean;
begin
  Result := 0;
  case Msg of
    WM_CREATE :
      begin
        TimeEditHandle := CreateWindowEx(0, 'Edit', '',
          WS_CHILD or WS_VISIBLE or WS_TABSTOP or ES_NOHIDESEL or ES_AUTOHSCROLL,
          30, 12, 90, 22, AHWnd, IDC_TIMESHOWEDIT, HInstance, nil);
        ShowTimeThreadHandle := CreateThread(nil, 0, @ShowTimeThreadProc, nil, 0, ThreadId);
      end;
    WM_KEYDOWN :
      begin
        ControlKeyDown := GetAsyncKeyState(VK_CONTROL) shr ((SizeOf(SHORT) * 8) - 1) <> 0;
        if (ControlKeyDown) and (AWParam = Ord('S')) then
        begin
          DestroyWindow(AHWnd);
        end;
      end;
    WM_CTLCOLORSTATIC :
      begin
        DC := AWParam;
        SetBKColor(DC, ColorToRGB(clBlack));
        SetTextColor(DC, ColorToRGB(clLime));
        Result := GetStockObject(DC_BRUSH);
      end;
    WM_DESTROY :
      begin
        CopyTextToClipBoard(GetText(TimeEditHandle));
        DestroyWindow(TimeEditHandle);
        SuspendThread(ShowTimeThreadHandle);
      end;
  else
    begin
      Result := DefWindowProc(AHWnd, Msg, AWParam, ALParam);
    end;
  end;
end;

Na pewno zachodzi na oknie komunikat WM_CTLCOLORSTATIC, gdyż zrobiłem lamerski test i wstawilem tam krótkieog Beepa, no i "bipał" :) Prosił bym o przykład jak to prawidłowo ogarnąc, no i to samo dla innych ewentualnych przyszłych kontrolek.

Drugi problem jaki napotkałem to bardziej eleganckie tworzenie okna pod Ctrl+S. Teraz pojawia się pasek tytułowy nad oknem, którego nie umiem zlikwidowac, a według Google wystarcza ponoć sama flaga WS_BORDER. Jednak tutaj nie zaskakuje albo robię coś nie tak, chociaż w tym kodzie jest inaczej.

Dodatkowo chciałbym aby wywołane okno nie tworzyło nic na belce paska zadań, ponieważ to włącza mu Focus i brzydko wygląda. Chciałbym mieć efekt jak dla okna po MessageBox z uchwytem dla zmiennej GomPlayerMainWindowHandle. Czyli nie traci focusa, nie pokazuje belek tytułowych i nie traci reakcji okno rodzica czyli głowne playera. Poniżej kod [wycinek] jak to jest zrobione teraz, bo inaczej mi nie wychodzi.

//...
procedure ShowTimeWindowThreadProc(Param : Pointer); stdcall;
var
  Msg : TMsg;
  WC : TWndClass;
  AppClass : PChar;
begin
  AppClass := ShowTime_Window_Class;
  WC.hinstance := hinstance;
  WC.lpfnwndproc := @WndProc;
  WC.hicon := LoadIcon(0, IDI_ASTERISK);
  WC.hcursor := LoadCursor(0, IDC_ARROW);
  WC.hbrbackground := COLOR_WINDOW;
  WC.lpszclassname := AppClass;
  RegisterClass(WC);
  TimeWindowHandle := CreateWindowEX(WS_EX_DLGMODALFRAME, AppClass, PChar(ShowTime_Window_Title),
    WS_BORDER, 20, 60, 200, 100, 0, 0, HInstance, nil);
  ShowWindow(TimeWindowHandle, SW_SHOW);
  while GetMessage(Msg, 0, 0, 0) do
  begin
    TranslateMessage(Msg);
    DispatchMessage(Msg);
  end;
end;
///...

Będę wdzięczny za wszelką pomoc. Sam Player do testów można pobrać ze strony http://player.gomlab.com/?language=eng i wspomnianą dllkę do kompilacji wystarczy przy zamkniętym programie wrzucić do jego katalogu. Wybrałem do spoofingu akurat tę, ponieważ miała najmniej importów w kodzie playera i można było ze źródeł modułów do Delphi 7 Enterprise wygooglować, jak powinny wyglądać wywołąnia tych funkcji oraz inne potrzebne w kodzie elementy. A takie kopiuj / wklej ułatwiło znacznie proces spoofingu.

Sorry za rozpisanie się. Jeżeli coś dla Was nie jest jasne pytajcie, ale opisałem najlepiej jak potrafię. Z góry dziękuję za wszelkie przykłady kodu rozwązującego moje problemy. A sam player mogę polecić. Bo VLC ma swoje plusy, ale niektóre rzeczy dla mnie zdecydowały, ze do plików offline bez napisów używam właśnie GomPlayera. No i łatwiej było mi go zespoofować, a pluginów pod VLC nie ogarniam, bo może stworzyłbym coś podobnego i do niego. Ale to zrobię może kiedyś, w przyszłości :)

EDT: zobaczyłem na MSDN i już wiem, że parametr przed HMenu i HInstance to okno rodzić do pokazania modalnie i już paska tytułowego na belce zadan nie ma, ale nadal pozostaje pojawianie się samego menu start oraz to jak zlikwidować tytul okna z editem, bo okno i tak będzie można docelowo zamykać Ctrl+S ponownie lub przyciskiem na nim samym. No i kwestia kolorów dla kontrolek. Także nadal liczę na pomoc, bez Was wiele raczej sam nie wskoram. I tak dobrze, że w tej wersji dało się samym oldskoolowym Cheat Engine namierzyć Pointera z adresem względem bazowego z liczbą sekund, o ile wiem starsze wersje był odporne na takie kombinacje i nie znalazłem prawidlowych danych w pamięci procesu, ale może xle szukałem. Wazne, że teraz działa ok, ale to dopiero zaczątek małego projektu, ponieważ czekam na pomoc od Was by ruszyć dalej z pracą.

0

Co do pierwszego to może?

Edit controls that are not read-only or disabled do not send the WM_CTLCOLORSTATIC message; instead, they send the WM_CTLCOLOREDIT message.
https://msdn.microsoft.com/pl-pl/library/windows/desktop/bb787524%28v=vs.85%29.aspx

0

Dzięki, to częściowo pomaga. Jednak nie wiem dlaczego kolor czcionki jest ok, ale tła jest inny niz biały dopiero kiedy Edit dostaje Focusa. Chyba to że w wątku co 500 ms w innym wariancie kodu jest zmieniany jego tekst, nie powinno mieć znaczenia? Bo teraz w innym wariancie kodu mojego projektu mam takie coś jak poniżej (wklejam tylko konkratny wycinek).

//...
const
  Wait_MS = 500;
  clLime = TColor($00FF00);
  clBlack = TColor($000000);

//...

function GetPlayingTime : string;
var
  OkStatus : boolean;
  HProcess : THandle;
  ImgBs, ImgSiz : DWORD;
  GomPid, TimeValue : WORD;
  PlayedTimeBaseAddress : DWORD;
begin
  Result := '';
  GomPid := GetCurrentProcessId;
  HProcess := OpenProcess(PROCESS_ALL_ACCESS, False, GomPid);
  if HProcess <> INVALID_HANDLE_VALUE then
  begin
    if GetModuleBaseAddress(GomPid, ExtractFileName(ParamStr(0)), ImgBs, ImgSiz) then
    begin
      PlayedTimeBaseAddress := ImgBs + Add_To_Base_Address;
      TimeValue := ReadPointer(HProcess, PlayedTimeBaseAddress, PlayTime_Add_Offset, vtWord, OkStatus);
      if OkStatus then
      begin
        Result := SecsToTimeStr(TimeValue);
      end;
    end;
  end;
  CloseHandle(HProcess);
end;

procedure ShowTimeThreadProc(Param : Pointer); stdcall;
var
  TimeStr : string;
begin
  while True do
  begin
    SetWindowLong(TimeWindowHandle, GWL_EXSTYLE, WS_EX_TOOLWINDOW and not WS_EX_APPWINDOW);
    TimeStr := GetPlayingTime;
    if GetText(TimeEditHandle) <> TimeStr then
    begin
      SetText(TimeEditHandle, TimeStr);
    end;
    Sleep(Wait_MS);
  end;
end;

function WndProc(AHWnd : HWND; Msg : UINT; AWParam : WPARAM; ALParam : LPARAM) : LRESULT; stdcall;
var
  DC : HDC;
  ThreadId : Cardinal;
  ControlKeyDown : boolean;
begin
  Result := 0;
  case Msg of
    WM_CREATE :
      begin
        TimeEditHandle := CreateWindowEx(0, 'Edit', '',
          WS_CHILD or WS_VISIBLE or WS_TABSTOP or ES_NOHIDESEL or ES_AUTOHSCROLL,
          30, 12, 90, 22, AHWnd, IDC_TIMESHOWEDIT, HInstance, nil);
        ShowTimeThreadHandle := CreateThread(nil, 0, @ShowTimeThreadProc, nil, 0, ThreadId);
      end;
    WM_KEYDOWN :
      begin
        ControlKeyDown := GetAsyncKeyState(VK_CONTROL) shr ((SizeOf(SHORT) * 8) - 1) <> 0;
        if (ControlKeyDown) and (AWParam = Ord('S')) then
        begin
          DestroyWindow(AHWnd);
        end;
      end;
    WM_CTLCOLOREDIT :
      begin
        DC := AWParam;
        SetBKColor(DC, ColorToRGB(clBlack));
        SetTextColor(DC, ColorToRGB(clLime));
        Result := GetStockObject(DC_BRUSH);
      end;
    WM_DESTROY :
      begin
        CopyTextToClipBoard(GetText(TimeEditHandle));
        DestroyWindow(TimeEditHandle);
        SuspendThread(ShowTimeThreadHandle);
      end;
  else
    begin
      Result := DefWindowProc(AHWnd, Msg, AWParam, ALParam);
    end;
  end;
end;
//...

No i pozostaje problem pojawiania się paska tytułowego okna oraz focusowania na pierwszy plan paska Start. Chciałbym tego uniknąć. Może masz Ty albo inni jakiś pomysł, to poprosił bym o przykłady kodów. Z góry dziękuję. No i oczywiście jeszcze raz dzękuję Tobie za bardzo szybką odpowiedź. Częściowo ruszyłem z miejsca ;)

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