WinApi - wygląd okna jak przy ustawieniach TForm

0

Witam.

Kombinuje z WinApi, przeglądam MSDNa, ale nadal mi nie wychodzi. Chce uzyskać taki efekt jak przy programowaniu
VCL kiedy to dla Formatki ustawimy własność BorderStyle na bsDialog, czyli bez ikonki programu, bez menu i tylko
przycisk do zamykania aplikacji mają być na pasku, a rosszerzanie formatki ma nie być możliwe. Dodatkowo chciałbym,
aby aplikacja nie pojawiała się na pasku zadań. Póki co zrobiłem tak jak poniżej, lecz aplikacja jest wtedy bez żadnych
przycisków i ma dośyć brzydką ramkę, jak dodam WS_EX_TOOLWINDOW to okno ma małą belkę tytułową oraz maly
przycisk do zamykania, a tego nie chcę. Poza tym wtedy kawałek formatki pod belką tytułową jest przeźroczysty i pod
nim widać to co jest w tle. Dlatego prosiłbym o jakiś przykład jak stworzyć takie okno jak opisałem przez CreateWindow
lub może CreateWindowEx, a później ukryć mu belkę na pasku zadan przez SetWindowLong. W aplikacjach VCL, nie ma
z tym problemów, ale w WinApi niestety mi nie wychodzi. Zaś analiza kodu modułu Forms nie za wiele mi pomogła tutaj.

function WndProc(Wnd : HWND; uMsg : UINT; wPar : WPARAM; lPar : LPARAM) : LRESULT; stdcall;
var
  St, StEx : LongWord;
begin
  Result := 0;
  case uMsg of
    WM_CREATE :
      begin
        St := GetWindowLong(Wnd, GWL_STYLE);
        StEx := GetWindowLong(Wnd, GWL_EXSTYLE);
        SetWindowLong(Wnd, GWL_EXSTYLE, not WS_EX_APPWINDOW);
      end;

// ....

Okno tworzę i pokazuje tak:

//...
  WindowHandle := CreateWindow(App_Class, 'Aplikacja odbierająca komunikat WM_COPYDATA',
    WS_VISIBLE + WS_SYSMENU {+ WS_TILEDWINDOW}, (Screen_Width - Window_Width) div 2,
    (Screen_Height - Window_Height) div 2, Window_Width, Window_Height, 0, 0, hInstance, nil);
  ShowWindow(WindowHandle, SW_SHOW);
0

hmmm.... zerknij do modulu Forms, jak by nie bylo tam jest wszystko robione na oknach ;]
znalazlem cos pod

procedure TCustomForm.CreateParams(var Params: TCreateParams);

widze, ze tam jest ustawianie stylu zaleznie od borderStyle...

0

Dobra, już sobie poradziłem, bo we wtyczce którą pisałem do Expressivo i tak użyłem DialogBoxParam i dialogu zapisanego w
pliku rc, w zasadzie to tylko jego namiastki bo okno jest niewidoczne. A przy okazji pytanie cimak albo ktoś inny, może wiecie
skąd można pobrać narzędzie DFM2Api? Ogólnie szukam czegoś gotowego co formatkę w dfm przerobi ładnie na wpisy do tc.
który można póxniej skompilowac brcc32.exe do postaci zasobu res? Niestety wszystkie linki padły. Tworzenie niemal od zera
przy pomocy ResHackera nie za bardzo mi się uśmiecha, a na napisanie od zera takiej aplikacji też za cienki jestem. Może jest
coś gotowego co konwertuje albo coś, czym wygodnie się tworzy Dialogi w plikach rc poza ResHAckerem oraz Restoratorem?

0

kiedys bardzo dawno temu bylo cos takiego jak resource workshop w borland pascalu(i chyba c++) dla wersji 16 bit. Nie wiem tez czy przypadkiemw express visualu tego nie ma (c++) normalnie mozna ustawiac komponenty na formatce.

0

Dzięki za odpowiedź, wolał bym takie coś jak to DFM2Api, ale nie ma chyba niestety jak napisać do
autora i poprośić o aktualny link ponieważ jest problem z dotarcia drogą emailową jak wnioskuje. z
błędów na stronie. A w web.archive, także nie ma innej wersji strony z jakimś linkiem do pobrania.

0

Zapomnialem odpowiedziec ale wtedy to znalazlem (z cujag 2000) i zapomnialem linku podac (a teraz znow nie moge znalezc) ale jak co mam u siebie (wlasnie czyszcze pulpit) wiec jak co to na email.

0

reichel: jak masz tego dfm2api i to nie jakiś problem dla Ciebie to wystaw na speedyshare.com ja to przerzuce na swoje konto w
mediafire żeby link nie wygasł i podam tutaj zainteresowanym. A jak nie to wrzuć też na www i ewentualnie podaj mi link na PW.

0

DFM2Api leży na DSP podaję link bezpośredni: http://delphi.icm.edu.pl/ftp/tools/dfm2api120.zip

0

Dzięki za linka, ale to jest chyba jakaś starsza wersja, bo pozwala tylko na wyciągnięcie dfma z exe. Chyba, że tak ten program
ma działać. Bo ja zrozumiałem inaczej że on nam z dfma stworzy plik ktory będzie można dodac i użyć jako dialog do zasobów.

0

Jest to prawie najnowsza wersja (do nowszej niestety nie mam dostępu). Na stronie producenta http://www.luigibianchi.com/dfm2api.htm jest napisane że jest wersja 1.2.2.164 Niestety strona dawno nie była aktualizowana a autor chyba porzucił projekt i przestał sie tym zajmować, bo nie da się pobrać z tej strony.

Nie mniej program działa tak jak tego oczekujesz: File->Open ładujesz plik DFM program analizuje forme gdy skończy w katalogu w którym jest plik DFM znajdziesz plik CPP a w nim szkielet procedury obsługi okna (dla C++ Bulder), HPP - nagłówki no i RC oraz RH w RC to gotowy do skompilowania plik zasobów a w RH są zdefiniowane stałe używane w pliku RC no i właśnie o te 2 ostatnie pliki Ci chodzi :)

0

A faktycznie, teraz przyjrzałem się że tworzy różne pliki, faktycznie taki plik mi odpowiada.
Szkoda tylko, że część kodu trzeba przerobić na Delphi, ale to nie takie trudne, chociaż dla
formatek dla ktorych chciałem to zastosować - musiał bym umieć w WinAPi zrobić jeszcze:
jak zabloować przy wprowadzaniu do Edita jakieś klawisze? Próowałem na próbę dla litery 'A'
to zrobić, ale mi nie wychodzi. Chcę osiągnąć taki efekt jak w aplikacji VCL mamy w zdarzeniu
OnKeyPress jak damy po Key := #0; Nie pomagało ustawianie wParam := 0; to próbowałem
coś w stylu poniższego kodu, ale to też nie działa. Dlatego jak ktoś wie to proszę o pomoc:

  iEditStyles := GetWindowLong(hCtlFirstNameEdit, GWL_STYLE);
  SetWindowLong(hCtlFirstNameEdit, GWL_STYLE, iEditStyles or ES_READONLY);

I teraz jeszcze jedno pytanie abym nie musiał tutaj tworzyć nowych wątków. Jak zrobić aby
dialog mial też ikonkę jeżeli jest ona w zasobach, bo na pasku jest, ale chcę obok tytułu
aplikacji aby również się ona pojawiła. Co zmienić? Póki co googluje aby okiełznać klawisze.

IDC_TMAINFORM DIALOGEX 126 65 146 117
EXSTYLE 0x00 | WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE
STYLE 0x00 | WS_POPUP | WS_CAPTION | WS_DLGFRAME | DS_MODALFRAME | DS_CENTER | WS_VISIBLE | DS_3DLOOK | DS_FIXEDSYS | WS_SYSMENU | WS_MINIMIZEBOX
CAPTION "Tytul aplikacji"
FONT 8, "MS Sans Serif", 400, 0
0

Ok naskrobałem przykład odpowiadający na oba pytania:

APIDemo.dpr (tu nic ciekawego)

program APIDemo;



{$R 'ApiDemo.res' 'ApiDemo.rc'}

uses
  Windows,
  uMain in 'uMain.pas';

begin
  InitDlg;
end.

APIDemo.rc (plik zasobów zrobiony na bazie Twojego)

#define IDI_MAINICON  100

IDI_MAINICON ICON "Res\MainIcon.ico"


#define IDC_TMAINFORM 1000
#define IDC_EDIT      10000


IDC_TMAINFORM DIALOGEX 126 65 146  117
EXSTYLE 0x00 | WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE
STYLE 0x00 | WS_POPUP | WS_CAPTION | WS_DLGFRAME | DS_MODALFRAME | DS_CENTER | WS_VISIBLE | DS_3DLOOK | DS_FIXEDSYS | WS_SYSMENU | WS_MINIMIZEBOX
CAPTION "Tytul aplikacji"
FONT 8, "MS Sans Serif", 400, 0
BEGIN
  EDITTEXT  IDC_EDIT, 10, 10, 100, 12, ES_AUTOHSCROLL | ES_LEFT
END

uMain.pas (tu jest wszystko czego potrzebujesz)

unit uMain;

interface
uses Windows, Messages;

const
  IDI_MAINICON  = 100;

  IDC_TMAINFORM = 1000;
  IDC_EDIT      = 10000;

var
  hInstance: Cardinal;
  hMainIcon: HICON;

  hDlg: Cardinal;
  hMyEdit: Cardinal;

  pOldMyEditProc: Pointer;
  pNewMyEditProc: Pointer;

  procedure InitDlg;
  function DialogProc(hWnd: HWND; uMsg, wParam, lParam: Longint): Bool; stdcall;
  function MyEditProc(hWnd: HWND; uMsg, wParam, lParam: Longint): Integer; stdcall;

implementation

procedure InitDlg;
var
  res: Integer;
begin
  hInstance:= GetModuleHandle(nil);

  res:= DialogBoxParamA(hInstance, MAKEINTRESOURCE(IDC_TMAINFORM),
     0, @DialogProc, 0);
  ExitProcess(res);
end;

function DialogProc(hWnd: HWND; uMsg, wParam, lParam: Longint): Bool; stdcall;
begin
  result:= False;
  case uMsg of
  WM_CLOSE:
    EndDialog(hWnd, 0);
  WM_INITDIALOG:
    begin
      hDlg:= hWnd;
      hMyEdit:= GetDlgItem(hWnd, IDC_EDIT);

      //fragment odpowiedzialny za blokowanie klawiszy
      //Tu sie pobawimy w Subclassing
      pNewMyEditProc:= @MyEditProc; //pobierz adres nowej procedury dla Edit
      //podmiana domyslnej procedury obslugi EDIT (zwraca asres poprzeniej)
      pOldMyEditProc:= Pointer(SetWindowLong(hMyEdit, GWL_WNDPROC,
        Integer(pNewMyEditProc)));

      //ladowanie ikony
      hMainIcon:= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MAINICON)) ;
      SendMessage(hWnd, WM_SETICON, 1, hMainIcon); //ustawienie ikony
      result:= True;
    end;
  end;
end;

//nowa procedura obslugi EDIT
function MyEditProc(hWnd: HWND; uMsg, wParam, lParam: Longint): Integer; stdcall;
begin
  case uMsg of
    WM_CHAR:
      begin
        if wParam = Ord('A') then //blokujemy lubimy A
        begin
          result:= 0;
          exit;
        end;
      end;
  end;
  //wywolanie starej (domyslnej) procedury obslugi EDIT
  result:= CallWindowProc(pOldMyEditProc, hMyEdit, uMsg, wParam, lParam);
end;

end.
0

Ogromne podziękowania dla Ciebie kAzek. Jestem Tobie niewyobrażalnie wdzięczny. Googlując i kombinują samodzielnie nie
byłem w stanie ruszyć z miejsca. A teraz będę miał dla satysfakcji napisaną prawie samodzielnie malutką aplkację w WinApi.
Wcześniej też tak kombinowałem mniej więcej tak jak Ty tylko że do obslugi Editów - stosowałem chyba z tego co pamiętam
procedurę, a nie funkcję albo źle zwracałem rezultat przez co obslugiwany Edit znikał lub program się zamrażal. A teraz jest
wszystko w porządku. Do pełni szczęści brakuje tylko aby Dfm2Api potrafił obsłużyć dfmy z Delphi wydanych po 2000 roku,
no ale zawsze jak coś jest extract i pod ręką mam też Delphi 3 na szczęście zostawione z sentymentu. A taki program, jest
jak dla mnie sporym ułatiwniem. Prosty "generatorek" z exeka zajmującego około 85 KB po spakowaniu - zajmuje, również
po spakowaniu UPX'em niecale 11 KB. Nie jest to majsterszytk w asmie, lecz zawsze czegoś się człowiek dłubiąc nauczy :)

0

Dzięki za pliki, ta wersja ma poprawioną chyba obslugę błędów.
Póki co napisałem proste dialogi takie jak chcialem w WinApi, a
program oczywiście przyda się w przyszlości jak będę coś rzeźbił.

0

Przecież to jest najstarsza opublikowana wersja 1.0.0 dostępna z kodem źródłowym na stronie producenta :/

0

Hmmm kurde a ja wywaliłem tę z linka od Ciebie, bo ta wersja też chyba działa ok, ale ma obslugę błędów lepszą jak coś, bo jak
w tej wersji co podałeś linka do niej kAzek to gdy wybrałem dfm z Delphi 7 to program wygenerowal jakiś niekopletny plik txt, no
i się zawiesił, że trzeba było zamknąć. Natomiast ta wersja co wrzucił reichell pokazuje elegancko komunikat o błędzie. Czasami z
programami tak bywa, że starsze wersje działają nieco lepiej. Szkod, że kod jest w C++, ktorego w ogole nie trawię, bo tak bym
może mając kod w Delphi rozwinął program aby działał jakoś z formatkami od Delphi 7 przynajmniej. Ale dobre i to co jest. Wiem
z readme, że w nowszej wersji jest więcej zmian, ale dla przygotowania pliku rc z formatki, na ktorej były tylko: Buttony, Edity i
Labele, to w zupełności mi taka wersja wystarczy. Chociaż mimo, że wedlug mnie własności Editów się nie rożniłły od pierwszego
kodu formatki, to przy robieniu kolejnego generatora Edity nie można było przełączać Tabulatorem oraz pierwszy z nich nie był w
momencie uruchomienia programu aktywny. Ale poradziłem sobie przekopiowalem własności Editów z pliku rc, w ktorym jest ok.
Dla pewności jeszcze raz dziekuję wszystkim za pomoc, ale przy okazji może jeszcze pytanie do Was albo kAzek może coś na to
będziesz umiał zaradzić. Mam taki dialog jak poniżej napisalem. I elegancko pokazuje ikonkę oraz tylko przycisk do zamknięcia.

IDC_TMAINFORM DIALOGEX 126 65 171 68
EXSTYLE 0x00 | WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE
STYLE 0x00 | WS_CAPTION | WS_BORDER | WS_VISIBLE | WS_SYSMENU | DS_CENTER
CAPTION "To tutaj akurat nieważne :)"
FONT 8, "MS Sans Serif", 400, 0

I wiadomo, że w VCL taki kod dla formatki w OnCreate:

  SetWindowLong(Application.Handle, GWL_EXSTYLE, WS_EX_TOOLWINDOW and not WS_EX_APPWINDOW);

Spowoduje, że nie będziemy mieć belki programu na pasku zadań, ale program będzie można przywołać w razie czego wciskając na
przykład Alt+Tab. Jednak jeżeli dla dialogu ustawię WS_EX_TOOLWINDOW nawet odając pobrane wcześniej przez GetWindowLong
style GWL_EXSTYLE, to dialog nie ma wprawdzie belki na pasku zadań, ale traci też ikonę, zmiejsza się pasek tytułowy i do tego
robi się mały przycisk do zamykania. A co najgorsze aplikacji nie można przywrócić przez Alt+Tab. Czy to co udaje się tylko pod
VCL jedynie tam zadziała. Czy jest sposob jakiś w WinAPI aby dialog miał ikonkę na belce tytułowej i ów belkę też o normalnych
rozmiarach, ale nie pokazywała się belka na pasku zadań. Czy takie rzeczy tylko w Erze, eee... to znaczy w VCL no i dla formatek?
Jeżeli jest jakiś sposób to prosił bym o przykład ustawianie not WS_EX_APPWINDOW dla Handle Dialogu też mi nic nie pomogło.
Bo w sumie jak się nie da, to jakoś przeżyję, ale myślałem że skoro mam tylko przycisk do zamykania - to może ukryć belkę.

0

No cóż Delphi jak powszechnie wiadomo stosuje pewien trick FormMain wcale nie jest głównym oknem programu. Dlatego w VCL nadanie stylu WS_EX_TOOLWINDOW dla Application.Handle nie powoduje zmian na pasku tytułu okna (gdybyś to zrobił dla Form1.Handle zobaczył byś efekt jak w WinApi).
No cóż skoro Delphi "oszukuje" to my też możemy:

Plik DPR jak w poprzednim przykładzie.

Plik RC.

#define IDI_MAINICON  100

IDI_MAINICON ICON "Res\MainIcon.ico"

#define IDC_TAPPFORM 1000
#define IDC_TMAINFORM 1001

IDC_TAPPFORM DIALOGEX 0 0 0 0
WS_EX_TOOLWINDOW
FONT 8, "MS Sans Serif", 400, 0
BEGIN
END

IDC_TMAINFORM DIALOGEX 126 65  171 68
EXSTYLE 0x00 | WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE
STYLE 0x00 | WS_CAPTION | WS_BORDER | WS_VISIBLE | WS_SYSMENU | DS_CENTER
CAPTION "To tutaj akurat nieważne :)"
FONT 8, "MS Sans Serif", 400, 0
BEGIN
END

PLIK PAS:

unit uMain;

interface
uses Windows, Messages;

const
  IDI_MAINICON  = 100;

  IDC_TAPPFORM  = 1000;
  IDC_TMAINFORM = 1001;


var
  hInstance: Cardinal;
  hMainIcon: HICON;

  hAppDlg: Cardinal;
  hMainDlg: Cardinal;

  procedure InitDlg;
  function HidenDialogProc(hWnd: HWND; uMsg, wParam, lParam: Longint): Bool; stdcall;
  function MainDialogProc(hWnd: HWND; uMsg, wParam, lParam: Longint): Bool; stdcall;


implementation

procedure InitDlg;
var
  res: Integer;
begin
  hInstance:= GetModuleHandle(nil);

  res:= DialogBoxParamA(hInstance, MAKEINTRESOURCE(IDC_TAPPFORM),
     0, @HidenDialogProc, 0);
  ExitProcess(res);
end;

function HidenDialogProc(hWnd: HWND; uMsg, wParam, lParam: Longint): Bool; stdcall;
begin
  result:= False;
  case uMsg of
  WM_CLOSE:
    EndDialog(hWnd, 0);
  WM_INITDIALOG:
    begin
      hAppDlg:= hWnd;

      hMainIcon:= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MAINICON)) ;
      SendMessage(hAppDlg, WM_SETICON, 1, hMainIcon);

      ShowWindow(hAppDlg, SW_HIDE); //na wszelki wypadek ale i bez tego to okno nie jest widoczne
      DialogBoxParamA(hInstance, MAKEINTRESOURCE(IDC_TMAINFORM), hWnd,
         @MainDialogProc, 0);

      result:= True;
    end;
  end;
end;

function MainDialogProc(hWnd: HWND; uMsg, wParam, lParam: Longint): Bool; stdcall;
begin
  result:= False;
  case uMsg of
  WM_CLOSE:
    begin
      EndDialog(hWnd, 0);
      SendMessage(hAppDlg, WM_CLOSE, 0, 0); //aby zamknąc okno aplikacji
    end;
  WM_INITDIALOG:
    begin
      hMainDlg:= hWnd;

      //hMainIcon:= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MAINICON)) ;
      SendMessage(hWnd, WM_SETICON, 1, hMainIcon);
    end;
  end;
end;


end.

Jak widać zrobiłem dodatkowe niewidoczne okno dialogowe i to ono jest głównym oknem aplikacji (zupełnie jak w Delphi) dzięki czemu możemy pozbyć się programu z paska zadań bez zmian wyglądu widocznego okna dialogowego.

0

Wielkie dzięki kAzek. Działa świetnie, chociaż chciałbym poprawić jeszcze jedną rzecz. Otóż mój generator pokazuje na belce
tytułowej po wyświetleniu najpierw tytulu programu losowe teksty. Robi to w wątku (kod poniżej). Jednak ja chcialbym mieć
taki efekt, że to co jest Application.Title normalnie pozostaje niezmienne. Tytuł dla IDC_TAPPFORM ustawiłem przez Caption
w pliku rc. jednak mój kod powoduje, że jak miną dwie sekundy po pokazaniu tytułu aplikacji, a ja przełączam się pomiędzy
oknami za pomocą Alt+Tab to tytuł aplikacji jest taki jak kawałek wypisanego w wątku losowego tekstu, a ja chciałbym mieć
zawsze taki sam tytuł. Czyli tak jak jest to analogicznie w VCL, że Application.Title sobie ustawiamy jakie chcemy, a zmienia
się tylko Caption formatki. U mnie AppHandle to uchwyt pobrany przy tworzeniu ukrytego okna bez belki, a DialogHandle to
uchwyt Dialogu który się wyświetla później. Poniżej wycinki kodu źródłowego. Bo w googlach natrafiłem wcześniej na jakimś
forum na kod, ktory wywoływał jakoś okno dialogowe z zasobów tak jakby robione to było przez Form.ShowModal, ale teraz
nie pamiętam co wpisałem dokładnie w googlach, coś z obejściem problemu z WM_CHAR szukałem. Jakbym jeszcze tylko to
jakoś okiełznał z Twoją pomocą to miałbym idealny program. Chociaż mam generator kluczy do jednego populanego klienta
ircowego pisany dawno temu w masmie i tam litery na pasku tytułowym są co kilkaset milisekund zmieniane - z wielkiej na
małą i odwrotnie. Jednak może da się osiągnąć to co chcę zrobić. Bo o ile wiem jak sprawdzałem w VCL'u, to się da zrobić.
Jeżeli w WinApi jest to problem, to trudno - podaruję sobie. Jednak fajnie było by to jakoś dopracować. I dodam również iż
z moich testów wynika, że nie ważne czy wątek uruchomiłem z ukrytego czy widocznego dialogu tuż po ustawieniu AppTitle.
W sumie to kosmetyka i aż tak bardzo mi nie przeszkadza, bo program ma swoją ikonę, ale fajnie było by to dopracować.

Procedura obsługi wątku:

procedure ThreadProc;
var
  S : string;
  R, LastR, I : integer;
  AppTitleArr : array[0..3] of string;
begin
  LastR := -1;
  AppTitleArr[0] := AppTitle;
  AppTitleArr[1] := 'Coded by olesio';
  AppTitleArr[2] := 'Made in pure WinApi';
  AppTitleArr[3] := 'Thanks to kAzek for help';
  while True do
  begin
    if LastR = -1 then
    begin
      R := 0;
      LastR := 0;
    end
    else
    begin
      repeat
        R := Random(Length(AppTitleArr));
      until R <> LastR;
      LastR := R;
    end;
    S := AppTitleArr[R];
    for I := 1 to Length(S) do
    begin
      SetWindowText(AppHandle, PChar(AppTitle));
      SetWindowText(DialogHandle, PChar(Copy(S, 1, I)));
      Sleep(120);
    end;
    Sleep(2000);
  end;
end;

Funkcja obsługi komunikatów w widocznym oknie:

function MainDlgProc(hWnd : HWND; Msg : UINT; wParam : wParam; lParam : lParam) : BOOL; stdcall;
var
  Buffer : array[0..128] of Char;
begin
  DialogHandle := hWnd;
  // ... tutaj obsluga przychodzących Msg
end;

Tworzenie ukrytego okna i w nim stworzenie wątku oraz tworzenie głownego widocznego okna:

function HidenDlgProc(hWnd: HWND; uMsg, wParam, lParam: Longint): Bool; stdcall;
var
  ThrID : Cardinal;
  Buffer : array[0..128] of Char;
begin
  Result := False;
  case uMsg of
  WM_CLOSE :
  begin
    EndDialog(hWnd, 0);
  end;
  WM_INITDIALOG:
    begin
      Randomize;
      ThrID := 58;
      AppHandle := hWnd;
      hMainIcon:= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MAINICON)) ;
      SendMessage(AppHandle, WM_SETICON, 1, hMainIcon);
      ShowWindow(AppHandle, SW_HIDE);
      GetWindowText(AppHandle, Buffer, SizeOf(Buffer));
      AppTitle := Buffer;
      CreateThread(nil, 0, @ThreadProc, nil, 0, ThrID);
        DialogBoxParamA(hInstance, MAKEINTRESOURCE(IDC_TMAINFORM), hWnd,
         @MainDlgProc, 0);
      Result:= True;
    end;
  end;
end;

var
  Res : Integer;
begin
  hInstance := GetModuleHandle(nil);
  Res := DialogBoxParamA(hInstance, MAKEINTRESOURCE(IDC_TAPPFORM),
     0, @HidenDlgProc, 0);
  ExitProcess(Res);
end.
0

Niestety nie wiem dlaczego tak jest :/ Próbowałem też ukrytym oknem tworzonym przez CreateWindow i to samo, może wieczorem będę miał czas to spróbuje coś pokombinować (jak coś to wyedytuję post chyba że ktoś napisze coś po mnie).

0

Nie wnikalem super dokladnie ale w VCL (ktore jest tylko obudowa winapi !) dziala to tak, ze jest ukryte okno i ono ma za zadanie wyswietlac tytul, chyba podobnie jest u Ciebie z ta roznica, ze uzywasz dialogo (one maja wspolna nazwe klas chyba ?!) a w VCL sa tworzone przez createwindowex i registerclass.

0

Być może, ale właśnie reichel / kAzek / ktokolwiek: jak stworzyć okno dialogowe przez CreateWindow, bo widziałem przykład w
google na jakimś forum o C, ale jak wspomniałem nie mogę go ponownie znaleźć. Poza tym jak próbowalem tworzyć okno, tak
jak w tutorialu o podstawach WinAPI (w artykułach w dziale Delphi) i w funckji obłusgi komunikatów dla okna po WM_CREATE
tworzyłem okno dialogowe przez DialogBoxParamA to i tak głownym oknem był mój dialog, okienko tworzone ze swoją klasą z
tego co kojarzę tworzyło się wcześniej i później zostało przysłaniane przez mój dialog i dalej efekt był taki sam, że tytuł całej
aplikacji zmieniał się też przy przełączaniu Alt+Tab. Coś pewnie namieszałem i trzeba jakoś inaczej pokazać dialog modalnie.

EDIT: Teraz mam tak (najważniejszy wycinek kodu) i albo pokazuje się belka aplikacji oraz dwa okna (w widoku Alt+Tab czyli
jeden ma nadal belkę, a drugi bez ikony i ze zmieniającym się tytułem). Nie umiem zrobić tak aby okno ze swoja klasą okna,
nie było widoczne na pasku zadań, ale widoczne w procesach i tak aby drugie okno dialogowe nie było osobnym procesem - w
oknie Alt+Tab widocznym). Czyli tak jak można zrobić bez problemów w VCL z użyciem OnCreate lub czasami CreateParams.
Jak się nie uda nic wykombinować to trudno. A terazs idę na mecz, bo niemiaszki się rozkręciły i już, jak widzę prowadzą 1:0.

// ...
procedure TestProc;
begin
  DialogBoxParamA(hInstance, MAKEINTRESOURCE(IDC_TMAINFORM), 0, @HidenDlgProc, 0);
end;

function WndProc(Wnd: HWND; uMsg: UINT; wPar: WPARAM; lPar: LPARAM): LRESULT; stdcall;
var
  ThrID : Cardinal;
begin
  Result := 0;
  AppHandle := Wnd;
  case uMsg of
    WM_ACTIVATE :
    begin
      SetForeGroundWindow(DialogHandle);
    end;
    WM_CREATE :
    begin
      ThrID := 0;
      hMainIcon := LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MAINICON));
      SendMessage(Wnd, WM_SETICON, 1, hMainIcon);
      CreateThread(nil, 0, @TestProc, nil, 0, ThrID);
    end;
    WM_DESTROY: PostQuitMessage(0);
    else Result := DefWindowProc(Wnd, uMsg, wPar, lPar);
  end;
end;

var
  Msg : TMsg;
  Wnd : TWndClass;
begin
  with Wnd do
  begin
    lpfnWndProc := @WndProc;
    hInstance := hInstance;
    lpszClassName := 'My1stApp';
    hbrBackground := COLOR_WINDOW;
  end;
  RegisterClass(Wnd);
  CreateWindow('My1stApp', 'Program pierwszy w WinAPI',
        WS_VISIBLE or WS_TILEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        0, 0, hInstance, NIL);
  while GetMessage(msg, 0, 0, 0) do DispatchMessage(msg);
end.
0

Dobra ale co chcesz uzyskac tworzac okno dialogowe bo wywolujac funkcje do tego przeznaczone i tak wywolasz CreateWindows(Ex) ale z odpowiednimi parametrami.

Moze w pkt. co twoje okno (nazwijmy je dialogowe) ma robic/miec cechy

0

Póki co dzięki kAziowi mam taki efekt jak poniżej - oprócz tego co w ostatnim myślniku.

A chcę aby mój dialog:

  • miał tylko przycisk zamknij (to robię oczywiście definiując dialog przez plik zasobów rc)
  • miał belki na pasku zadań (tutaj póki co używam sposobu, ktory podpowiedział mi kAzek)
  • miał ikonkę (to wiem jak zrobić, tak jak mi kAzek pokazał przy użyciu pliku rc i SendMessage)
  • miał ustawiony tytuł belki w wątku oraz pętli (tak jak to pokazałem we wcześniejszym postcie)
  • przy przełączaniu się kombinacją Alt+Tab ma być widoczna ikonka dla dialogu, a nie pusta jak przy
    braku ikony, a jednocześnie tytul aplikacji pokazany w okienku Alt+Tab ma być ciągle taki sam, nie
    zmieniać się tak jak zmienia się w wątku, że zmiamiast "Tytuł aplikacji" jest widoczne, na przyklad:
    "Coded by". W sumie to co chcę zrobić to tylko drobna kosmetyka, lecz nie umiem poiradzić z tym
    w WinAPI, dlatego proszę o pomoc. Jak nie macie pomysłów to trudno. Zostanie kod taki jak teraz.
0

No wlasnie jak wspominalem czuje, ze dialog jest zlym wyborem bo to strasznie prosta opcja (chyba ze pozniej setwindowlong). Wydaje mi sie, ze tu moze pomoc pierwszy parametr funkcji createwindowex odpowiadajacy za dodatkowy styl okna patrz w okolicach WS_EX_CONTROLPARENT lub WS_EX_TOOLWINDOW (ale nie wiem czy to niz zmniejszy paska).

Aczkolwiek delphiowe aplikacje zmieniaja napis w oknie alt tab tylko nie w pasku ? Moglbys walnac przyklad w VCL bo chyba sie coraz bardziej gubie ?!

0

A olać to, Niech zostanie jak jest. To i tak było pisanie na wprawkę. Chodzi o to, że właśnie w VCL
mamy osobno Application.Handle i JakasForm.Handle i dlatego możemy zmieniać tekst tylko dla u
góry widocznej belki tytułowej. A w WinAPI, przynajmniej tak jak ja zrobiłem zmienia się zarowno
tytuł belki dialogu no i chociaż nie jest on jedynym to jednocześnie zmienia się nazwa aplikacji, w
oknie Alt+Tab również widoczna. Mimo tego, iż wątek, ktory zmienia tytuł używa handle dialogu.
Jednak jak ktoś wpadnie jeszcze na coś to proszę piszcie. Póki co zrobione i odłożone "na półkę".

0

Podane rozwiazanie:

  1. Okno glowne CreateWindowEx z parametrem wsomnianym, to jest to application.handle
  2. Dialog

W belece w pasku start sie nie zmienia, w alt tab sie zmienia (stosownie do okna)

O to chodzi ?

0
reichel napisał(a)

W belece w pasku start sie nie zmienia, w alt tab sie zmienia (stosownie do okna)

O to chodzi ?

Belki na pasku zadań - nie ma, bo ukrylem ją tak jak doradził mi kAzek.
Zmienia się wlaśnie również napis w oknie od Alt+Tab, a tego nie chcę.

0

A jestes wstanie podac jakis przyklad co tak ma bo wszystko co mam pod reka zmienia tytul okna w alt tab ?
Nawet jakis projekt w vcl.

0

O kurcze, nie wiem jakim cudem, ale jednak pod VCL jest tak samo, a dałbym sobie łeb ściąć, że jakoś
wcześniej ten kod działał inaczej, bo może coś inaczej robiłem. Tak czy siak - nie zaryzykuję swojego i
tak pustego łba ;) Prawdopodobnie, skoro w VCL się nie da, bo chyba się nie da, to i w WinAPI też, a i
uważam, ze nie ma co więcej kombinować. Po prostu mojej "zachcianki" nie da się przełożyć na kod ;/

//...
var
  Form1 : TForm1;
  AppTitle : string;
  DialogHandle : Cardinal;

implementation

{$R *.dfm}

procedure ThreadProc;
const
  Wait_MS = 2000;
var
  S : string;
  I, R : integer;
  AppTitleArr : array[0..3] of string;
begin
  R := Low(AppTitleArr) + 1;
  AppTitleArr[0] := AppTitle;
  AppTitleArr[1] := 'Coded by olesio';
  AppTitleArr[2] := 'Made in pure WinAPI';
  AppTitleArr[3] := 'Thanks to kAzek for help';
  Sleep(Wait_MS);
  while True do
  begin
    S := AppTitleArr[R];
    for I := 1 to Length(S) do
    begin
      SetWindowText(DialogHandle, PChar(Copy(S, 1, I)));
      SetWindowText(Application.Handle, PChar(AppTitle));
      Sleep(120);
    end;
    Sleep(Wait_MS);
    R := R + 1;
    if R > High(AppTitleArr) then
    begin
      R := Low((AppTitleArr));
    end;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  ThrID : Cardinal;
begin
  ThrID := 1;
  DialogHandle := Form1.Handle;
  AppTitle := Application.Title;
  SetWindowLong(Application.Handle, GWL_EXSTYLE, WS_EX_TOOLWINDOW and not WS_EX_APPWINDOW);
  CreateThread(nil, 0, @ThreadProc, nil, 0, ThrID);
end;

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