WinApi - zabawa z tworzeniem wrappera

WinApi - zabawa z tworzeniem wrappera
TheAifam5
  • Rejestracja:ponad 12 lat
  • Ostatnio:około 6 lat
  • Postów:127
0

Teraz mam zamiar stworzyc klase dzieki ktorej znikna te Windowsowe lParam oraz wParam i calosc komunikatow bedzie funkcjonowac na Identyfikatorach obiektow a nie jak mam teraz poprzez (HWND)lParam ;) Hmm rownie dobrze moge stworzyc funkcje w Utils tworzaca okno w osobnym watku i zwracac wskaznik do okna ;) no ale to troszke nie estetyczne.

Hmm a jesli tak zrobic by obsluga komunikatow byla w innym watku, a przy tworzeniu watkow wyslac mu potrzebne parametry?


Wole programowac niz spac :)
Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:3 minuty
0

Pętla komunikatów (ta z GetMessage/DispatchMessage) musi być, i musi „blokować”. GetMessage pobiera z systemowej kolejki komunikat, a DispatchMessage wywołuje WndProc odpowiedniego okna.

Możesz mieć więcej niż jedno okno na raz (CreateWindow, CreateWindow, ... i dopiero: while(GetMessage)).
Okna mogą mieć to samo WNDCLASS albo inne.
Możesz też otworzyć i pokazać okno (CreateWindow, ShowWindow) w odpowiedzi na jakieś zdarzenie, czyli wewnątrz WndProc. Niczego ci to przecież nie blokuje.

Rozdziel po prostu ideę otwarcia okna (Open) od uruchomienia pętli komunikatów (nazwijmy to Run).
Pierwsze nie blokuje, drugie blokuje i blokować musi.

Gdyby nie pętla, to po otwarciu okna program dotarłby zaraz do końcowego } funkcji main i od razu się zakończył.

edytowany 2x, ostatnio: Azarien
Zobacz pozostały 1 komentarz
TheAifam5
@_0x666_ Pisalem ale w Qt oraz wxWidgets ale pisanie wrappera do WinAPI to juz inna bajka.
06
W kwestii blokowania/nieblokowania aplikacji wcale nie taka inna (wx'y znam dość dobrze). Dobrze napisanie GUI działa w jednym wątku (głównym).
Azarien
@aifam96: to wszystko działa natej samej zasadzie: najpierw tworzone są okna i inne zasoby, a potem odpalana jest blokująca funkcja która zawiera pętlę komunikatów i trwa przez cały czas działania programu. w Qt ta funkcja nazywa się QApplication::exec().
Bartosz Wójcik
być może PeekMessage by pomogło, chociaż jak czytam ten wątek to też mam wrażenie, że ktoś na siłe próbuje odkrywać koło, jest przecież WTL http://www.codeproject.com/Articles/3867/WTL-for-MFC-Programmers-Part-II-WTL-GUI-Base-Class który całkiem fajnie sobie z tym radzi
Azarien
@Bartosz Wójcik: WTL wymaga ATL, a tego w darmowych Visualach nie ma, nie mówiąc już o GCC.
TheAifam5
  • Rejestracja:ponad 12 lat
  • Ostatnio:około 6 lat
  • Postów:127
0

Caly czas mam blad "GetLastError returned 578".
ERROR_NO_PAGEFILE {No Paging File Specified} No paging file was specified in the system configuration.
PageFile mam wylaczone bo moj lapek ma 6GB ram i postanowilem mniej obciazyc dysk. Jak sie pozbyc tego bledu? Czy po prostu zignorowac to?


Wole programowac niz spac :)
TheAifam5
  • Rejestracja:ponad 12 lat
  • Ostatnio:około 6 lat
  • Postów:127
0

Witam.
Zniechecilem sie troche do pisania tego poniewasz mam pelno problemow.. ;) musze sie pouczyc o wskaznikach itp i o calym winapi.

Poki co, zamieszczam caly kod zrodlowy do wgladu.
Jesli w CObject zrobi sie poprzez std::wstring& to zadziala.

EDIT:
Oczywiscie niedlugo do tego wroce;)


Wole programowac niz spac :)
edytowany 1x, ostatnio: TheAifam5
TheAifam5
  • Rejestracja:ponad 12 lat
  • Ostatnio:około 6 lat
  • Postów:127
0

To tak po za tematem. :) Przepraszam :<
Czy w klasie Window ktora inicjuje dopiero poprzez konstruktor ktora dziedziczy z innej klasy Object moge wykonac funkcje z klasy np: Object::Initialize()
Pseudokod konstruktora Window:

Kopiuj
Window::Window()
    :Object()
{
Object::Initialize();
}

Pytam poniewasz pewna wartosc zwraca mi zawsze NULL a GetLastError zwraca 0.


Wole programowac niz spac :)
edytowany 1x, ostatnio: TheAifam5
Azarien
no to Object czy FObject?
TheAifam5
Oj co to za roznoca.. przeciez to pseudokod :) Chodzi o Object. Zedytowalem
Azarien
różnica taka, że nikt poza tobą nie wie, czy to literówka w pseudokodzie, czy przyczyna problemu. w konstruktorze można wywoływać metody, ale nie wirtualne.
TheAifam5
  • Rejestracja:ponad 12 lat
  • Ostatnio:około 6 lat
  • Postów:127
0

Witam,
mam problem, jesli ustawie lParam jako this to wywala mi blad i GetLastError wynosi 578.
Natomiast ustawiajac NULL, pokazuje sie okno jest ok.
Klasa Object tworzy uchwyt poprzez CreateWindowEx - a to jest w funkcji Initialize(LPVOID) a ta funkcje wywoluje klasa BaseWindow w konstruktorze z parametrem LPVOID ktora przekazuje do funkcji Initialize.
Klasa MainWindow dziedziczy BaseWindow. Tylko dziedziczy.

Screenshoty, moze cos jeszcze powiedza(Ptr WndProc: jest zawsze NULL poniewaz nie jest przekazywany lParam(wywala gdy this albo dziala bo jest NULL ustawiony):
Przy podaniu LPVOID w parametrze funkcji Initialize jako this w klasie BaseWindow: http://prntscr.com/4lcui3
Przy podaniu LPVOID jako NULL: http://prntscr.com/4lewgw

Pseudokod (mniej wiecej tak...;p by pokazac gdzie sa rozmieszczone komunikaty z konsoli):

Kopiuj
class Application
{
private:
public:
    static HINSTANCE GetInstance() { return reinterpret_cast<HINSTANCE>(GetModuleHandle(NULL)); };
};

class Object
{
private:
    HWND hWnd;
public:
    Object() {};
    bool Initialize(Object* lParam)
    {
	std::cout << "HEX FObject:" << std::hex << this << std::endl;
	std::cout << "GetLastError Before CreateWindowEx: " << std::hex << GetLastError() << std::endl;
        hWnd = ::CreateWindowEx(WS_EX_CLIENTEDGE, L"Test", L"Test", WS_OVERLAPPEDWINDOW, 20, 20, 200, 300, NULL, NULL, Application::GetInstance(), (LPVOID)lParam);
	std::cout << "GetLastError After CreateWindowEx: " << std::hex << GetLastError() << std::endl;
	if (hWnd == NULL)
		std::cout << "Cannot create window class!" << std::hex << GetLastError() << std::endl;
    };
};

class BaseWindow : public Object
{
public:
    BaseWindow() : Object() {
        WNDCLASSEX wcx;
	wcx.cbSize = sizeof(WNDCLASSEX);

	wcx.style = CS_HREDRAW | CS_VREDRAW | CS_DROPSHADOW;
	wcx.lpfnWndProc = [](HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)->LRESULT CALLBACK
	{
		BaseWindow* pWnd;

		if (uMsg == WM_NCCREATE)
		{
			// get the pointer to the window from lpCreateParams which was set in CreateWindow
			SetWindowLong(hWnd, GWL_USERDATA, (LONG)((LPCREATESTRUCT(lParam))->lpCreateParams));
		}

		// get the pointer to the window
		pWnd = reinterpret_cast<BaseWindow *>(GetWindowLong(hWnd, GWL_USERDATA));

		// if we have the pointer, go to the message handler of the window
		// else, use DefWindowProc
		if (pWnd)
		{
			switch (uMsg)
			{
			case WM_CREATE:
				std::cout << "Main Window Create.......SUCCESS" <<std::endl;
				break;
			case WM_CLOSE:
				DestroyWindow(hWnd);
				break;

			case WM_DESTROY:
				PostQuitMessage(0);
				break;
			};
			return 0;
		}
		std::cout << "Ptr WndProc: " << std::hex << pWnd << std::endl;
		std::cout << "Ptr MSG: " << std::hex << uMsg << std::endl;
		std::cout << "Ptr wParam: " << std::hex << wParam << std::endl;
		std::cout << "Ptr lParam: " << std::hex << lParam << std::endl;
		return DefWindowProc(hWnd, uMsg, wParam, lParam);
	};
	wcx.cbClsExtra = 0;
	wcx.cbWndExtra = 0;
	wcx.hInstance = Application::GetInstance();
	wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
	wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	wcx.lpszMenuName = NULL;
	wcx.lpszClassName = L"Test";
	wcx.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
	std::cout << "GetLastError Before initializing Fobject: " << std::hex << GetLastError() << std::endl;
        Initialize(this);
	std::cout << "GetLastError After initializing Fobject: " << std::hex << GetLastError() << std::endl;
	std::cout << "HEX FBaseWindow:" << std::hex << this << std::endl;
    };
};

class MainWindow : public BaseWindow
{
public:
    MainWindow() : BaseWindow() { std::cout << "HEX MainWindow:" << std::hex << this << std::endl; };
};

Wole programowac niz spac :)
edytowany 13x, ostatnio: TheAifam5
06
  • Rejestracja:prawie 20 lat
  • Ostatnio:około rok
  • Postów:2440
0

Błąd 578 to ERROR_NO_PAGEFILE, i raczej nie ma on związku z Twoją aplikacją. Włącz plik wymiany, problem zniknie.

BTW, dlaczego Object tworzy okno? Logiczniej byłoby, gdyby tworzone było w BaseWindow lub oknach pochodnych. Jaka w ogóle jest rola klasy Object?

Kopiuj
hWnd = ::CreateWindowEx(...);
if (g_hWnd == NULL)
	std::cout << ...

Uchwyty...

edytowany 1x, ostatnio: _0x666_
TheAifam5
Rola klasy Object jest to ze jest dla wszystkich, BaseWindow dziedziczy po nim HWND bo przeciez kontrolki tez maja HWND ;) Wiec wole napisac Jedna klase ktora bede mogl przenosic wszedzie wskaznikami i np sprawdzic sb HWND a na jej podstawie klase okna ;) i wgl.. Tylko czemu dla this wywala 578 a dla NULL wywawla aby 6 .. czy ile tam jest
06
  • Rejestracja:prawie 20 lat
  • Ostatnio:około rok
  • Postów:2440
0

Wiec wole napisac Jedna klase ktora bede mogl przenosic wszedzie wskaznikami i np sprawdzic sb HWND a na jej podstawie klase okna ;)

No ale tę rolę spokojnie może pełnić BaseWindow, bo przecież po tej klasie będzie dziedziczyć każda kontrolka, każde okno. Wtedy jest porządek, bo jeśli jest okno, to ma uchwyt. Object jest zbyt ogólny (z nazwy) i może przecież dotyczyć obiektów nieokienkowych, bez uchwytów. Porządek w kodzie musi być... ;)

p.s. komentarze nie służą do kontynuowania dyskusji na główny temat.

TheAifam5
hmmm... zgadza sie.. wiesz pisze tak jak poprzednio lecz troche ze zmieniona skladnia ;) zastosuje sie , thx ;)
06
Przypomniało mi się. Do Object daj wirtualny destruktor, a w BaseWindow zablokuj operator= i konstruktor kopiujący.
TheAifam5
  • Rejestracja:ponad 12 lat
  • Ostatnio:około 6 lat
  • Postów:127
0

Serio XD???
Problem tutejszy lezal w lambdzie... a dokladnie za switch ktory po zakonczeniu wykonywal return 0;
A gdzies w jakims kursie znalazlem ze po kazdej wiadomosci zwracal 0 ;) Widocznie mieli blad bo nie moge zwracac 0, poniewaz reszte eventow klasy okna nie zostaje wykonana.. ;) przez co program lezal zawsze


Wole programowac niz spac :)
edytowany 1x, ostatnio: TheAifam5
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)