WinApi - zabawa z tworzeniem wrappera

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

Witam,
Czy jest szybszy sposób pisania wrappera do WinAPI od wypisywania po kolei WM_* ? (Chodzi o wrapper do pisania okien, kontrolek i innych takich tam customowych rzeczy w WinAPI)

Kopiuj
	virtual void OnCreate();
	virtual void OnDestroy();
	virtual void OnMove();
	virtual void OnSize();
	virtual void OnActivate(int state);
	virtual void OnSetFocus();
	virtual void OnKillFocus();
	virtual void OnEnable();
	virtual void OnSetRedraw();
	virtual void OnSetText();
	virtual void OnGetText();
	virtual void OnGetTextLength();
	virtual void OnPaint();
	virtual void OnClose();
#ifndef _WIN32_WCE
	virtual void OnQueryEndSession();
	virtual void OnQueryOpen();
	virtual void OnEndSession();
#endif
	virtual void OnQuit();
	virtual void OnEraseBkgnd();
	virtual void OnSysColorChange();
	virtual void OnShowWindow();
	virtual void OnWinIniChange();
#if(WINVER >= 0x0400)
	virtual void OnSettingChange();
#endif
	virtual void OnDevModeChange();
	virtual void OnActivateApp();
	virtual void OnFontChange();
	virtual void OnTimeChange();
	virtual void OnCancelMode();
	virtual void OnSetCursor();
	virtual void OnMouseActivate();
	virtual void OnChildActivate();
	virtual void OnQueueSync();
	virtual void OnGetMinMaxInfo(MINMAXINFO* info);
	virtual void OnPaintIcon();
	virtual void OnIconEraseBkgnd();
	virtual void OnNextDlgCtl();
	virtual void OnSpoolerStatus();
	virtual void OnDrawItem();
	virtual void OnMeasureItem();
	virtual void OnDeleteItem();
	virtual void OnVKeyToItem();
	virtual void OnCharToItem();
	virtual void OnSetFont();
	virtual void OnGetFont();
	virtual void OnSetHotkey();
	virtual void OnGetHotkey();
	virtual void OnQueryDragIcon();
	virtual void OnCompareItem();
#if(WINVER >= 0x0500)
#ifndef _WIN32_WCE
	virtual void OnGetObject();
#endif
#endif
	virtual void OnCompacting();
	virtual void OnCommNotify();
	virtual void OnWindowPosChanging();
	virtual void OnWindowPosChanged();
	virtual void OnPower(int state);
	virtual void OnCopyData(COPYDATASTRUCT* data);
	virtual void OnCancelJournal();
#if(WINVER >= 0x0400)
	virtual void OnNotify();
	virtual void OnInputLangChangeRequest();
	virtual void OnInputLangChange();
	virtual void OnTCard();
	virtual void OnHelp();
	virtual void OnUserChanged();
	virtual void OnNotifyFormat(int state);
	virtual void OnContextMenu();
	virtual void OnStyleChanging();
	virtual void OnStyleChanged();
	virtual void OnDisplayChanged();
	virtual void OnGetIcon();
	virtual void OnSetIcon();
#endif
	virtual void OnNCCreate();
	virtual void OnNCDestroy();
	virtual void OnNCCalcSize();
	virtual void OnNCHitTest();
	virtual void OnNCPaint();
	virtual void OnNCActivate();
	virtual void OnGetDlgCode();
#ifndef _WIN32_WCE
	virtual void OnSyncPaint();
#endif
	virtual void OnNCMouseMove();
	virtual void OnNCLButtonDown();
	virtual void OnNCLButtonUp();
	virtual void OnNCLButtonDblClk();
	virtual void OnNCRButtonDown();
	virtual void OnNCRButtonUp();
	virtual void OnNCRButtonDblClk();
	virtual void OnNCMButtonDown();
	virtual void OnNCMButtonUp();
	virtual void OnNCMButtonDblClk();
#if(_WIN32_WINNT >= 0x0500)
	virtual void OnNCXButtonDown();
	virtual void OnNCXButtonUp();
	virtual void OnNCXButtonDblClk();
#endif
#if(_WIN32_WINNT >= 0x0501)
	virtual void OnInputDevice();
#endif
	virtual void OnInput();
	virtual void OnKeyFirst();
	virtual void OnKeyDown();
	virtual void OnKeyUp();
	virtual void OnChar();
	virtual void OnDeadChar();
	virtual void OnSysKeyDown();
	virtual void OnSysKeyUp();
	virtual void OnSysChar();
	virtual void OnSysDeadChar();
#if(_WIN32_WINNT >= 0x0501)
	virtual void OnUniChar();
	virtual void OnKeyLast();
	virtual void OnUnicodeNoChar();
#else
	virtual void OnKeyChar();
#endif
#if(WINVER >= 0x0400)
	virtual void OnImeStartComposition();
	virtual void OnImeEndComposition();
	virtual void OnImeComposition();
	virtual void OnImeKeyLast();
#endif
	virtual void OnInitDialog();
	virtual void OnCommand();
	virtual void OnSysCommand();
	virtual void OnTimer();
	virtual void OnHScroll();
	virtual void OnVScroll();
	virtual void OnInitMenu();
	virtual void OnInitMenuPopup();
#if(WINVER >= 0x0601)
	virtual void OnGesture();
	virtual void OnGestureNotify();
#endif
	virtual void OnMenuSelect();
	virtual void OnMenuChar();
	virtual void OnEnterIdle();
#if(WINVER >= 0x0500)
#ifndef _WIN32_WCE
	virtual void OnMenuRButtonUp();
	virtual void OnMenuDrag();
	virtual void OnMenuGetObject();
	virtual void OnUnInitMenuPopup();
	virtual void OnMenuCommand();

#ifndef _WIN32_WCE
#if(_WIN32_WINNT >= 0x0500)
	virtual void OnChangeUIState(int lState, int rState);
	virtual void OnUpdateUIState(int lState, int rState);
	virtual void OnQueryUIState(int lState, int rState);

#endif /* _WIN32_WINNT >= 0x0500 */
#endif

#endif
#endif /* WINVER >= 0x0500 */
	virtual void OnCtlColorMsgBox();
	virtual void OnCtlColorEdit();
	virtual void OnCtlColorListBox();
	virtual void OnCtlColorBtn();
	virtual void OnCtlColorDlg();
	virtual void OnCtlColorScrollBar();
	virtual void OnCtlColorStatic();
	virtual void OnMouseFirst();
	virtual void OnMouseMove();
	virtual void OnLButtonDown();
	virtual void OnLButtonUp();
	virtual void OnLButtonDblClk();
	virtual void OnRButtonDown();
	virtual void OnRButtonUp();
	virtual void OnRButtonDblClk();
	virtual void OnMButtonDown();
	virtual void OnMButtonUp();
	virtual void OnMButtonDblClk();
#if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)
	virtual void OnMouseWhell();
#endif
#if (_WIN32_WINNT >= 0x0500)
	virtual void OnXButtonDown();
	virtual void OnXButtonUp();
	virtual void OnXButtonDblClk();
#endif
#if (_WIN32_WINNT >= 0x0600)
	virtual void OnMouseWhell();
#endif
#if (_WIN32_WINNT >= 0x0600)
	virtual void OnMouseLast();
#elif (_WIN32_WINNT >= 0x0500)
	virtual void OnMouseLast();
#elif (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)
	virtual void OnMouseLast();
#else
	virtual void OnMouseLast();
#endif
	virtual void OnParentNotify();
	virtual void OnEnterMenuLoop();
	virtual void OnExitMenuLoop();
#if(WINVER >= 0x0400)
	virtual void OnNextMenu();
	virtual void OnSizing();
	virtual void OnCaptureChanged();
	virtual void OnMoving();
	virtual void OnPowerBoardcast();
#endif

Wole programowac niz spac :)
edytowany 3x, ostatnio: TheAifam5
MI
Nie lepiej pouczyć się Qt/wxWidgrets niż wymyślać koło na nowo?
TheAifam5
@Miziak wolisz apke ktora ma 20 mb i gowno robi(tylko wyswietla okno) w Qt a w wxWidgets mialaby z 2 mb lub 3.. czy apke ktora ma niecale 20 kb.... Wybralbym wxWidgets ale ona nie ma wsparcia dla DirectX9 a to mi bardzo potrzebne.
TheAifam5
@Bartosz Wójcik ok fajnie super... no ale co to mnie nauczy o WinAPi. Tworzac wlasny wrapper dodaje to co mi sie podba do aplikacji, bez zbednego kodu. A przy tym ucze sie jak to wszystko dziala, o komunikatach, o wskaznikach itd.
MI
Głupie jest upieranie się nad tym WinApi, po pierwsze strata zbędnego czasu, po drugie lepiej go(czas) poświęcić na coś przyszłościowego - Qt, C#, Jave itd a nie coś w czym się praktycznie nie pisze bo są wygodniejsze narzędzia. Jak to mawiał mój profesorek od Algorytmów programista jest z natury leniwy i chodzi na skróty żeby sobie życie ułatwić więc i Ty posłuchaj reszty i sobie je ułatw ^^
TheAifam5
@Miziak ale to moja sprawa co ja robie. Wiem, przyznam Ci racje ze przyszlosc nalezy wiazac z QT, C# oraz Jave. Jave i C# znam dobrze wiec to nie dla mnie problem. Chodzi o C++, nauka obiektowosci, jak wykorzystywac wskazniki i reference. C++ to temat bardzo obszerny lecz co mnie takiego nauczy w C++ QT po za tworzeniem okien, ukladanie w WYSIWYG kontrolek. Pisze sam i w GUI mam to co ja potrzebuje a w razie czego rozszezam i jest nie dosc ze mniejszy rozmar aplikacji koncowiej to na dodatek w razie bledu, moge go sb zlokalizowac. A co jesli w QT bedzie bug? ...
TheAifam5
... Nie musze czekac az autorzy go poprawia. W swojej aplikacji, w swoim frameworku czy tam wrapperze mam pelna kontrole ;) Wlasnie o kontrole nad kodem tez mi glownie chodzi. Nie mam zamiaru poprawiac bledu np jesli zaistnieje w QT i kompilowac 10GB by moc sb wrescie skorzystac.
MI
Z referencji korzysta się tak samo jak w innych językach z wyjątkiem jawnego "pokazywania" jej użycia w parametrach funkcji/metod. Z tymi bugami to się rozpędzasz za bardzo nawet gdy korzystam z Archa(rolling release distro) z głównymi frameworkami takimi jak Qt czy GTK problemów nie widziałem, wcześniej miałem postawionego debiana unstable też było wszystko dobrze a stał ok 3lata a Tobie się wydaje, że w stable release jest łatwo znaleźć bug? Gwarantuję Ci, że w podstawowych kontrolkach które użyjesz go nie znajdziesz bynajmniej nie tak prosto. ...
TheAifam5
Oj w QT wersji 4 czesto mialem bledy w frameworku... jeszcze chyba za czasu Kbuntu 9.04 .. nie pamietam za dobrze...
MI
Nie wiem co to jest ten WYSIWYG ale domyślam się, że chodzi Ci o graficzny designer. Qt(czy też wx'y i inne) nie wymusza na Tobie używania designer'a równie dobrze możesz kodzić GUI z palca. skompilowane paczki Qt dla windows ważą ok 600mb z całym Qt Creatorem więc ja nie widzę problemu przy współczesnych łączach parę minut ściągania jak Cię ten rozmiar tak boli to to źródełka wx'ów w 7z mają 16mb można szybko skompilować i wrócić do pracy.
MI
To pewnie Ci całe KDE na tym Kubuntu z tymi bugami padło? ^^
Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 10 godzin
0

Ło rany, że też ci się chce to tak robić :-)

Pytanie jak u ciebie ma wyglądać procedura okna.
Czy to jest coś w rodzaju:

Kopiuj
case WM_CREATE: OnCreate(); break;
case WM_DESTROY: OnDestroy(); break;

Taki kod może być trochę niewydajny, zwłaszcza że chcesz tam wsadzić wszystkie message'e jak leci.
Ale nie żeby to miało specjalnie znaczenie...

Trzeba by zobaczyć jak to jest zrobione w istniejących bibliotekach, zwłaszcza w MFC które jest dość cienkim wrapperem na WinAPI.
Ja nie znam szczegółów implementacji, ale na pewno nie działa to tak że jest kilkaset funkcji wirtualnych które są zawsze odpalane nawet jeśli są puste.

Ja tam nie widzę sensu robienia takiego full-wypasionego wrappera na wszystko. Ostatnio zacząłem pisać program pod WinAPI, jednocześnie powstaje minimalistyczny wrapper w którym jest tylko to co potrzebne w programie.

edytowany 1x, ostatnio: Azarien
TheAifam5
Jak na razie przepisywalem to wszystko ;) Ale jak napisales w ten sposob to zrozumialem ze robie to zle ;) Wiec tez inny sposob znalazlem. Gdybys nie odpisal... Pewnie teraz skonczylbym robic te "virtual void" i zaczal za procedury okna po kolei ;)
TheAifam5
  • Rejestracja:ponad 12 lat
  • Ostatnio:około 6 lat
  • Postów:127
0

A czy dobry sens by stworzyc typedefa funkcji oraz map?

Kopiuj
typedef long (* tyMessageHandler)(Window &, HWND, long, long);
typedef std::map<long, tyMessageHandler> tyMessageMap;
typedef tyMessageMap::iterator tyMessageIterator;

a tam gdzie procedura okna zrobic

Kopiuj
    tyMessageIterator it;
    it = GetMessageHandler(message);
    if(it != NULL)
      return (it->second)((*wnd), hwnd, wparam, lparam);

Jak bedziee z stabilnoscia oraz jak bedzie z szybkoscia tego wrapperAa? Czy bedzie dobrze dzialac z kazdym komunikatem?


Wole programowac niz spac :)
edytowany 3x, ostatnio: TheAifam5
kq
Moderator C/C++
  • Rejestracja:prawie 12 lat
  • Ostatnio:2 dni
  • Lokalizacja:Szczecin
1

Nie możesz porównać iteratora do NULLa, tylko do std::end(tyMessageMap). Jeśli chodzi o szybkość, unordered_map jest szybszym kontenerem.


TheAifam5
  • Rejestracja:ponad 12 lat
  • Ostatnio:około 6 lat
  • Postów:127
0

Chciabym uzyc do tego biblioteke boost... Jakich funkcji moge uzyc do tego(map, iterator, cos moze z komunikatami, pointerami - smart ptr ale do winapi?)?


Wole programowac niz spac :)
spartanPAGE
Mapy, iteratory, smart pointery masz w bibliotece standardowej, nie potrzebujesz do tego boosta.
TheAifam5
Ale mam bardzo duze przyzwyczajenie i w kazdym projekcie C++ korzystam z Boosta. Ale latwo tez przejsc na std ;) wiec bez roznicy
Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 10 godzin
1
Kopiuj
tyMessageHandler handler = tyMessageMap[message];
if (handler != nullptr)
    handler(...);
TheAifam5
Pewnie ten sposob tez Ci sie przyda ;) albo pewnie juz na niego wpadles i korzystasz ;p
kq
Ten sposób może doprowadzić do prawie nieograniczonego rozrostu mapy i nie jest thread-safe. Warto o tym wspomnieć przed użyciem.
TheAifam5
  • Rejestracja:ponad 12 lat
  • Ostatnio:około 6 lat
  • Postów:127
0
Kopiuj
tyMessageHandler CMessages::GetMessageHandler(long message)
{
	tyMessageHandler msgH = g_maps[message];

	return msgH != nullptr ? msgH : nullptr;
}

Zgrzeszylem gdzies?


Wole programowac niz spac :)
edytowany 2x, ostatnio: TheAifam5
Zobacz pozostałe 2 komentarze
TheAifam5
Uzyje metody find z powodu tego ze jest bezpieczniejsza.
06
To nie kwestia bezpieczeństwa, tylko optymalizacji. Operator [] dodaje pozycję jeśli nie ma jej w mapie, czyli po chwili będziesz miał mapę wypełnioną pozycjami/komunikatami, które nie będą miały przypisanego handlera.
TheAifam5
Czy do find moge uzyc nullptr czy jest cos innego zalecanego?
06
Zajrzyj do dokumentacji. find zwraca iterator, więc nie nullptr, tylko iterator zwrócony przez metodę end.
kq
find możesz bezpiecznie używać z wielu wątków jednocześnie bez synchronizacji (zakładając brak dodawania nowych zapisów do mapy). operatora[] nie możesz. Ergo, find jest metodą bezpieczniejszą.
TheAifam5
  • Rejestracja:ponad 12 lat
  • Ostatnio:około 6 lat
  • Postów:127
0

@_0x666_ tak wiem, ze zwraca.

Teraz zostala sprawa z dodawaniem do mapy. Czytalem ze poprzez [] jest bezpieczniej niz "insert" a na dodatek operator [] sprawdza czy juz istnieje.
Wiec skoro sprawdza czy juz istnieje to jak mi pokaze ze nie moze go dodac? Poprzez exception?

Kopiuj
g_maps[message] = handler;

Wole programowac niz spac :)
edytowany 2x, ostatnio: TheAifam5
kq
Moderator C/C++
  • Rejestracja:prawie 12 lat
  • Ostatnio:2 dni
  • Lokalizacja:Szczecin
2

Po prostu nadpisze obecną wartość. Insert tak samo. Polecam poczytanie dokumentacji: http://en.cppreference.com/w/cpp/container/map


TheAifam5
dzieki przyda sie ;) ja jakas gowniana znalazlem dokumentacje
Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 10 godzin
1

Ten sposób może doprowadzić do prawie nieograniczonego rozrostu mapy i nie jest thread-safe.

  1. lista komunikatów nie jest prawie nieograniczona, jest dość konkretnie ograniczona a wydaje mi się, że lepiej by ten NULL dodał się sam do mapy i był wyszukiwany potem już szybko, niż żeby za każdym razem przeszukiwana była mapa...
    Trzeba by to pomierzyć co jest szybsze, a nie zakładać z góry że operator[] considered harmful :-)

  2. WndProc z tego co mi wiadomo nie musi być thread-safe.

Azarien
kontrargument do 1: możliwość ataku denial-of-service — złośliwy program mógłby wysyłać do naszego okna bzdurne losowe komunikaty, a my byśmy pożerali coraz więcej pamięci.
kq
Moderator C/C++
  • Rejestracja:prawie 12 lat
  • Ostatnio:2 dni
  • Lokalizacja:Szczecin
1

lista komunikatów nie jest prawie nieograniczona, jest dość konkretnie ograniczona a wydaje mi się, że lepiej by ten NULL dodał się sam do mapy i był wyszukiwany potem już szybko, niż żeby za każdym razem przeszukiwana była mapa...
Lista komunikatów może i nie jest nieograniczona, ale może tam dostawać skądś śmieciowe wartości. W przypadku zwykłej mapy pewnie masz rację jeśli chodzi o wydajność, ale w przypadku unordered już bym się poważnie zastanowił (powiększenie jest kosztowne, a potem wyszukanie w przypadku kolizji jest droższe).

WndProc z tego co mi wiadomo nie musi być thread-safe.
Fakt, nie pomyślałem o kontekście użycia, to był raczej taki ogólny komentarz.


TheAifam5
  • Rejestracja:ponad 12 lat
  • Ostatnio:około 6 lat
  • Postów:127
0

Witam ponownie. Mam pewien problem. Naprawde nie mam pojecia co jest nie tak:

AifamFramework.lib(WinAPI_Window.obj) : error LNK2001: unresolved external symbol "private: static class WinAPI_Messages * WinAPI_Window::g_waMsg" (?g_waMsg@WinAPI_Window@@0PAVWinAPI_Messages@@A)

Kopiuj
#pragma once
class WinAPI_Window
{
private:
	static WinAPI_Messages* g_waMsg;
public:
	WinAPI_Window(HINSTANCE hInst, LPCWSTR lpClassName, int nCmdShow);
	~WinAPI_Window();
};
Kopiuj
#include "stdafx.h"
#include "WinAPI_Messages.h"
#include "WinAPI_Window.h"

WinAPI_Window::WinAPI_Window(HINSTANCE hInst, LPCWSTR lpClassName, int nCmdShow)
{
	g_waMsg = new WinAPI_Messages();
}

Logi:

Kopiuj
1>------ Rebuild All started: Project: A, Configuration: Debug Win32 ------
1>  stdafx.cpp
1>  main.cpp
1>  DirectX9.cpp
1>  Generating Code...
1>AifamFramework.lib(WinAPI_Window.obj) : error LNK2001: unresolved external symbol "private: static class WinAPI_Messages * WinAPI_Window::g_waMsg" (?g_waMsg@WinAPI_Window@@0PAVWinAPI_Messages@@A)
1>c:\users\theaifam5\documents\visual studio 2013\Projects\A\Debug\A.exe : fatal error LNK1120: 1 unresolved externals
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========

Build Summary
-------------
00:02.367 - Failed  - Debug Win32 - A\A.vcxproj

Total build time: 00:02.367

========== Rebuild All: 0 succeeded or up-to-date, 1 failed, 1 skipped, Completed at 9/4/2014 8:41:17 PM ==========

1>------ Rebuild All started: Project: AifamFramework, Configuration: Debug Win32 ------
1>  stdafx.cpp
1>  WinAPI_Window.cpp
1>  WinAPI_Messages.cpp
1>  Generating Code...
1>  AifamFramework.vcxproj -> c:\users\theaifam5\documents\visual studio 2013\Projects\A\Debug\AifamFramework.lib
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========

Build Summary
-------------
00:01.554 - Success - Debug Win32 - AifamFramework\AifamFramework.vcxproj

Total build time: 00:01.554

========== Rebuild All: 1 succeeded or up-to-date, 0 failed, 1 skipped, Completed at 9/4/2014 8:48:47 PM ==========

Wole programowac niz spac :)
edytowany 3x, ostatnio: TheAifam5
0

Musisz w pliku cpp zadeklarować:

Kopiuj
WinAPI_Messages* WinAPI_Window::g_waMsg = 0; 

Poza tym, czemu to static?

TheAifam5
  • Rejestracja:ponad 12 lat
  • Ostatnio:około 6 lat
  • Postów:127
0

Poniewaz:

Kopiuj
LRESULT CALLBACK WinAPI_Window::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	tyMessageHandler tMsgHand = WinAPI_Window::g_waMsg->GetMessageHandler(msg);
[...]
}

A WNDPROC musi byc statyczne.


Wole programowac niz spac :)
0

Masz mały błąd myśleniowy. WndProc w WinAPI_Window musi być static(tzn. nie musi, ale to inna bajka), ale dlaczego u ciebie g_waMsg to static. Bez sensu. Kompletnie nie obiektowo. Poza tym, za każdym razem jak walisz konstruktor WinAPI_Window to alokujesz na nowo g_waMsg. Ty traktujesz statica jako składową klasy, ale ty musisz to traktować jako zmienną globalną, i wprawdzie tak ją nazwałeś (g_ = global, s_ = static [Jak tak bardzo notacje chcesz stosować]).

TheAifam5
To masz moze pomys jak to zrobic by WndProc nie bylo statyczne?
0

To jest źle zaprojektowane.
Kiedyś jak pisałem wrapper to robiłem coś w ten deseń:

Kopiuj
class CWindow
{
private:
    CWndRect m_Rect;

    HWND m_hWnd;

protected:
    bool m_bIsInitialized;

public:
    CWindow();
    virtual ~CWindow();

    virtual CWndRect GetRect();
    virtual void SetRect(CWndRect Rect, bool bResizeWindow);

    virtual HWND GetHwnd();
    virtual void SetHwnd(HWND hWnd);

    virtual void ShowWindow();
    virtual void HideWindow();

    virtual bool IsVisible();

    virtual bool CreateClass() = 0;

    virtual bool CreateControls() = 0;

    virtual LRESULT WindowProcess(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) = 0;

    virtual void Destroy() = 0;

    virtual bool IsInitialized();

};

I jak chcę stworzyć okno np. About to robię nową klasę dla takiego okna:

Kopiuj
class CAboutWindow : public CWindow
{
private:
    CStatic * m_pStaticYearLicense;
    CStatic * m_pStaticCopyright;
    CStatic * m_pStaticCompilationDate;
    CStatic * m_pStaticTitle;

    CButton * m_pButtonClose;

public:
    CAboutWindow();
    ~CAboutWindow();

    bool CreateClass();

    bool CreateControls();

    LRESULT WindowProcess(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

    bool InitWindow();

    void Destroy();

    void ProcessControls(ECtrlId Id, EAction Action);

    void OnClose();

};

I w CreateClass takiej klasy walę:

Kopiuj
LRESULT __stdcall tAboutWindowProcess(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

bool CAboutWindow::CreateClass()
{
    WNDCLASSEX wc;
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = 0;
    wc.lpfnWndProc = tAboutWindowProcess;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = CCtrl::GetSingleton()->GetModuleInstance();
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = "win32_about_window";
    wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    if(!::RegisterClassEx(&wc))
        return false;

    return true;
}

LRESULT __stdcall tAboutWindowProcess(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    return CCtrl::GetSingleton()->GetAboutWindow()->WindowProcess(hWnd, uMsg, wParam, lParam);
}

Oczywiście lepiej by było walić SetWindowLong z thisem, ale po prostu mi się nie chciało, ponieważ okna w moim programie były pojedyncze, każde miało swoją właściwość, i takie rozwiązanie było dla mnie w pełni dobre.
Oczywiście do tego robiłem własne klasy buttonów, staticów, editów itd. i tworzenie wyglądało powiedzmy tak:

Kopiuj
bool CAboutWindow::CreateControls()
{
    m_pStaticYearLicense = new CStatic();
    if(!m_pStaticYearLicense)
        return false;
    m_pStaticYearLicense->Init(this, "blabla", Static, CWndRect(15, 158, 90, 13), NULL, CCtrl::GetSingleton()->GetFontById(0));
..
}

void CButton::Init(CWindow * pParentWnd, StringT & sName, ECtrlId eId, CWndRect & Dimension, DWORD dwAdditionalFlags, HFONT hFont)
{
    HWND hWnd;

    hWnd = ::CreateWindowEx(
        0,
        WC_BUTTON,
        sName.C_Str(),
        WS_VISIBLE | WS_CHILD | dwAdditionalFlags,
        0, 0,
        0, 0,
        pParentWnd->GetHwnd(),
        (HMENU)eId,
        CCtrl::GetSingleton()->GetModuleInstance(),
        NULL);
    if(!hWnd)
        return;

    SendMessage(hWnd, WM_SETFONT, (WPARAM)hFont, FALSE);

    this->SetHwnd(hWnd);

    this->SetRect(Dimension, true, true);

    this->ShowControl();
}

Oczywiście każda kontrolka dziedziczy z bazowej klasy CControl i wtedy jest dosyć przyjemnie.
Pamiętaj, że właściwie musisz do każdego okna podchodzić oddzielnie, bo tworzenie klasy(WNDCLASSEX) w WinApi nie jest domyślne tak jakby. Można tam ustalić sporo rzeczy, a walenie wszystkiego do argumentów nie jest fajne.

TheAifam5
  • Rejestracja:ponad 12 lat
  • Ostatnio:około 6 lat
  • Postów:127
0

Witam mam problem. Otoz napisalem tam troche, okno sie wyswietla ale nie reaguje natomiast WndProc dziala poniewasz po umieszczeniu MessageBoxa wywala go caly czas. Aplikacja tak jakby sie zamraza.
Kod jest bardzo zlozony i korzysta z dziedziczenia oraz wirtualnych funkcji.
Kod:

Kopiuj
LRESULT CALLBACK Utils::MsgRouter(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
		CBaseWindow *This = 0;

		if (uMsg == WM_NCCREATE){
			SetWindowLong(hWnd, GWL_USERDATA, long((LPCREATESTRUCT(lParam))->lpCreateParams));
		}

		This = (CBaseWindow *)GetWindowLong(hWnd, GWL_USERDATA);

		if (This){
			return This->WndProc(hWnd, uMsg, wParam, lParam);

		}
}

int CBaseWindow::Destroy()
{
	while (GetMessage(&GetMSG(), NULL, 0, 0))
	{
		TranslateMessage(&GetMSG());
		DispatchMessage(&GetMSG());
	}

	return (int)GetMSG().wParam;
}

bool CMainWindow::Initialize(const std::wstring& text)
{
	WNDCLASSEX wcex;

	wcex.cbSize = sizeof(WNDCLASSEX);

	wcex.style = CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc = Utils::MsgRouter;
	wcex.cbClsExtra = 0;
	wcex.cbWndExtra = 0;
	wcex.hInstance = GetInstance();
	wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground = (HBRUSH)RGB(0, 0, 0);
	wcex.lpszMenuName = NULL;
	wcex.lpszClassName = GetWindowClassName();
	wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

	if (FAILED(RegisterClassEx(&wcex)))
		return false;

	this->g_szWindowTitle = text.c_str();

	g_hWnd = CreateWindowEx(
		WS_EX_CLIENTEDGE,
		GetWindowClassName(),
		GetWindowTitle(),
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT, 
		NULL,
		NULL,
		GetInstance(),
		this);

	if (!g_hWnd)
	{
		if (g_hWnd == INVALID_HANDLE_VALUE){
			MessageBox(NULL, L"CreateWindowEx failed!", L"Error", MB_OK | MB_ICONERROR);
		}

		MessageBox(NULL, L"CreateWindowEx failed!\nGetLastError" + (int)GetLastError(), L"Error", MB_OK | MB_ICONERROR);
		return false;
	}

	ShowWindow(g_hWnd, SW_NORMAL);
	UpdateWindow(g_hWnd);

	return true;
}

LRESULT CALLBACK CMainWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_DESTROY: //Po umieszczeniu tutaj MessageBoxa i nacisniecia X w programie nie wywala go
                MessageBox(NULL, L"", L"", NULL);
		DestroyWindow(hWnd);
		break;
	default: //Po umieszczeniu tutaj MessageBoxa wywala tak czesto jak by go diabel opetal
		MessageBox(NULL, L"" + uMsg, L"", NULL);//Wywala dziwaczne znaki a takze i tekst
		return DefWindowProc(hWnd, uMsg, wParam, lParam);
		break;
	}
}

HINSTANCE CBaseWindow::GetInstance()
{
	return (HINSTANCE)GetModuleHandle(NULL);
}

Czy czegos tu brakuje?


Wole programowac niz spac :)
edytowany 1x, ostatnio: TheAifam5
mwl4
L"CreateWindowEx failed!\nGetLastError" + (int)GetLastError() -> LOL? Ty weź się najpierw za podstawy programowania bo ty nie wiesz co robisz.
Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 10 godzin
0

Wywal DestroyWindow z WM_DESTROY, bo to DestroyWindow właśnie wysyła WM_DESTROY - wpadasz w nieskończoną pętlę.

Sekwencja zamknięcia okna jest taka:
Kliknięcie X albo naciśnięcie Alt+F4, albo inny legalny sposób zamknięcia okna wysyła WM_CLOSE.
Domyślna procedura WM_CLOSE wykonuje DestroyWindow().
We własnej obsłudze WM_CLOSE można np. wyświetlić message boksa typu "Czy na pewno?" albo "Czy zapisać zmiany?". Po czym wywołać DestroyWindow albo nie.

Funkcja DestroyWindow zamyka okno. Zanim okno zostanie zniszczone, wysyłany jest komunikat WM_DESTROY.
Domyślne WM_DESTROY nie robi nic. Własne - może zwalniać jakieś zasoby, pamięć - przydzielone w WM_CREATE.
Po obsłużeniu WM_DESTROY okno przestaje istnieć i nie można już temu zapobiec.

edytowany 1x, ostatnio: Azarien
TheAifam5
Hehe... VS mi sie zbugowal i nawet ProcessExplorerem nie moge zabic programu :) Co mam zrobic? Pisze mi ze nie mam praw a jestem na Administratorze. Ale dziwne ze moglem go zamrozic.
TheAifam5
Haha ! Dobre ;) Tak wgl wystarczylo wylogowac i zalogowac sie jeszcze raz
TheAifam5
  • Rejestracja:ponad 12 lat
  • Ostatnio:około 6 lat
  • Postów:127
0

Log:

Kopiuj
'A.exe' (Win32): Loaded 'C:\Users\TheAifam5\Documents\Visual Studio 2013\Projects\A\Debug\A.exe'. Symbols loaded.
'A.exe' (Win32): Loaded 'C:\Windows\SysWOW64\ntdll.dll'. Cannot find or open the PDB file.
'A.exe' (Win32): Loaded 'C:\Windows\SysWOW64\kernel32.dll'. Cannot find or open the PDB file.
'A.exe' (Win32): Loaded 'C:\Windows\SysWOW64\KernelBase.dll'. Cannot find or open the PDB file.
'A.exe' (Win32): Loaded 'C:\Windows\SysWOW64\user32.dll'. Cannot find or open the PDB file.
'A.exe' (Win32): Loaded 'C:\Program Files (x86)\Visual Leak Detector\bin\Win32\vld_x86.dll'. Cannot find or open the PDB file.
'A.exe' (Win32): Loaded 'C:\Windows\SysWOW64\msvcp120d.dll'. Cannot find or open the PDB file.
'A.exe' (Win32): Loaded 'C:\Windows\SysWOW64\msvcr120d.dll'. Cannot find or open the PDB file.
'A.exe' (Win32): Loaded 'C:\Windows\SysWOW64\gdi32.dll'. Cannot find or open the PDB file.
'A.exe' (Win32): Loaded 'C:\Windows\SysWOW64\advapi32.dll'. Cannot find or open the PDB file.
'A.exe' (Win32): Loaded 'C:\Program Files (x86)\Visual Leak Detector\bin\Win32\dbghelp.dll'. Cannot find or open the PDB file.
'A.exe' (Win32): Loaded 'C:\Windows\SysWOW64\msvcrt.dll'. Cannot find or open the PDB file.
'A.exe' (Win32): Loaded 'C:\Windows\SysWOW64\sechost.dll'. Cannot find or open the PDB file.
'A.exe' (Win32): Loaded 'C:\Windows\SysWOW64\rpcrt4.dll'. Cannot find or open the PDB file.
'A.exe' (Win32): Loaded 'C:\Windows\SysWOW64\sspicli.dll'. Cannot find or open the PDB file.
'A.exe' (Win32): Loaded 'C:\Windows\SysWOW64\cryptbase.dll'. Cannot find or open the PDB file.
'A.exe' (Win32): Loaded 'C:\Windows\SysWOW64\bcryptprimitives.dll'. Cannot find or open the PDB file.
'A.exe' (Win32): Loaded 'C:\Windows\SysWOW64\imm32.dll'. Cannot find or open the PDB file.
'A.exe' (Win32): Loaded 'C:\Windows\SysWOW64\msctf.dll'. Cannot find or open the PDB file.
'A.exe' (Win32): Loaded 'C:\Windows\SysWOW64\nvinit.dll'. Cannot find or open the PDB file.
'A.exe' (Win32): Loaded 'C:\Program Files (x86)\NVIDIA Corporation\coprocmanager\detoured.dll'. Cannot find or open the PDB file.
'A.exe' (Win32): Loaded 'C:\Program Files (x86)\NVIDIA Corporation\coprocmanager\Nvd3d9wrap.dll'. Cannot find or open the PDB file.
'A.exe' (Win32): Loaded 'C:\Windows\SysWOW64\setupapi.dll'. Cannot find or open the PDB file.
'A.exe' (Win32): Loaded 'C:\Windows\SysWOW64\cfgmgr32.dll'. Cannot find or open the PDB file.
'A.exe' (Win32): Loaded 'C:\Program Files (x86)\NVIDIA Corporation\coprocmanager\nvdxgiwrap.dll'. Cannot find or open the PDB file.
Visual Leak Detector Version 2.4RC2 installed.
'A.exe' (Win32): Loaded 'C:\Windows\SysWOW64\uxtheme.dll'. Cannot find or open the PDB file.
'A.exe' (Win32): Loaded 'C:\Windows\SysWOW64\combase.dll'. Cannot find or open the PDB file.
'A.exe' (Win32): Loaded 'C:\Windows\SysWOW64\dwmapi.dll'. Cannot find or open the PDB file.
CreateWindowEx failed!teWindowEx failed!'A.exe' (Win32): Loaded 'C:\Windows\SysWOW64\ole32.dll'. Cannot find or open the PDB file.
'A.exe' (Win32): Loaded 'C:\Windows\SysWOW64\kernel.appcore.dll'. Cannot find or open the PDB file.
rorndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!ndowEx failed!teWindowEx failed!The program '[8188] A.exe' has exited with code 0 (0x0).

Kod:

Kopiuj
LRESULT CALLBACK CMainWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	OutputDebugString(L"" + uMsg);
	switch (uMsg)
	{
	case WM_CLOSE:
		DestroyWindow(hWnd);
		break;
	default:
		return DefWindowProc(hWnd, uMsg, wParam, lParam);
		break;
	}
}

Nadal to samo. Nie mam pojecia. Parametr

uMsg
w
CMainWindow::WndProc
jak by wyciek pamieci mial. Program jest, ale jakby martwy, nie mozna nim ruszac, zmienaic rozmiaru.

Do analizy moze sie przydac: http://prntscr.com/4k2yli
Zdj zrobione podczas wywolywania procedury WndProc, klikania, proby ruszania oknem oraz proby zamkniecia. Aby tylko widac klikanie.
Wykonuje sie podczas klikania to: WM_NCHITTEST oraz WM_SETCURSOR
Proba zamkniecia to: WM_SETCURSOR

Stworzylem takze przycisk lecz...nadal nic.


Wole programowac niz spac :)
edytowany 3x, ostatnio: TheAifam5
06
L&quot;&quot; + uMsg <--- pewny jesteś tego wyrażenia?
TheAifam5
Nope. Jednak poprawilem to wyrazenie i zapisalem w formacie hex uzywajac wsprintf
Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 10 godzin
0

'A.exe' (Win32): Loaded 'C:\Windows\SysWOW64\ntdll.dll'. Cannot find or open the PDB file.

http://msdn.microsoft.com/en-us/library/b8ttk8zy%28v=vs.100%29.aspx

Kopiuj
    if (!g_hWnd)
    {
        if (g_hWnd == INVALID_HANDLE_VALUE){

Jeśli g_hWnd wynosi NULL, no to nie wynosi INVALID_HANDLE_VALUE.

Kopiuj
L"CreateWindowEx failed!\nGetLastError" + (int)GetLastError()

Tak się na pewno c-stringów nie łączy.

TheAifam5
  • Rejestracja:ponad 12 lat
  • Ostatnio:około 6 lat
  • Postów:127
0

Ok. Siedzialem prawie do 5 rana myslac co jest nie tak.. Z tego co wyczytalem potrzeba uzyc SetWindowSubclass, pozniej poprzez SUBCLASSPROC odczytywac komunikaty, lecz co z WndProc ktora dostaje lParam z CreateWindowEx?


Wole programowac niz spac :)
edytowany 1x, ostatnio: TheAifam5
Azarien
do czego ci subclass?
06
  • Rejestracja:prawie 20 lat
  • Ostatnio:około rok
  • Postów:2440
1
Kopiuj
this->g_szWindowTitle = text.c_str();

Jakiego typu jest g_szWindowTitle?

TheAifam5
LPCWSTR g_szWindowTitle; a text to std::wstring
06
No to masz następny błąd. c_str zwraca adres tymczasowy, ponieważ po wyjściu z metody parametr text jest niszczony. Nie rozumiem, po co bawisz się w gołe wskaźniki, jeśli możesz użyć bezpiecznych kontenerów (w tym przypadku wstring)?
TheAifam5
Chciaem zachowac troche Windowsowego stylu ale widze ze to same problemy XD
06
No chyba po to piszesz wrapper na okienkowe WinAPI, żeby pozbyć się tego "windowsowego stylu".
TheAifam5
  • Rejestracja:ponad 12 lat
  • Ostatnio:około 6 lat
  • Postów:127
0

Przesle moze to co zrobilem bo naprawde nie wiem co jest nie tak..
W zalaczniku kody zrodlowe.

Tak wyglada main.cpp

Kopiuj
#include "stdafx.h"
#include "Utils.h"
#include "CMainWindow.h"

int APIENTRY WinMain(_In_ HINSTANCE hInstance,
					 _In_opt_ HINSTANCE hPrevInstance,
					 _In_ LPSTR    lpCmdLine,
					 _In_ int       nCmdShow)
{
	srand((unsigned int)(time(NULL)));

	//UNREFERENCED_PARAMETER(hPrevInstance);
	//UNREFERENCED_PARAMETER(lpCmdLine);

	

	CMainWindow main;
	if (!main.Initialize(L"Test"))
		return 1;
		
	main.Show();

	return main.Destroy();
}

///Edit:
Usunalem "virtual" z MainWindow "bool CreateControls(HWND hWnd);"


Wole programowac niz spac :)
edytowany 2x, ostatnio: TheAifam5
Azarien
skąd jest to aes.h?
TheAifam5
Usun to aes.h, Do testow nie jest ci potrzebna ona jeszcze nie jest zainicjowana w caly system. sa tylko funkcje kodujace i dekodujace w klasie Utils. Najwazniejsze dla mnie jest teraz dzialanie WndProc.
Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 10 godzin
1
Kopiuj
std::wstring* GetWindowClassName();

Nie zwracaj wstring*, zwracaj wstring. Nie po to miałeś przejść na kontenery, by się znowu bawić we wskaźniki.

Zresztą ta metoda jest niepotrzebna.

Kopiuj
int CBaseWindow::Destroy()
{
	while (GetMessage(&GetMSG(), NULL, NULL,NULL))
	{
		TranslateMessage(&GetMSG());
		DispatchMessage(&GetMSG());
	}

	return (int)GetMSG().wParam;
}

Już pomijając fakt, że ta metoda absolutnie nie powinna nazywać się Destroy(), tylko np. Run(), to przejechałeś się na manii robienia akcesorów, tam gdzie nie są potrzebne, albo gdzie - tak jak tutaj - są szkodliwe.

Wywal GetMSG, wywal g_msg. To ma być zmienna lokalna:

Kopiuj
MSG msg;
	while GetMessage(msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
TheAifam5
  • Rejestracja:ponad 12 lat
  • Ostatnio:około 6 lat
  • Postów:127
0

Brawo @Azarien udalo sie :) troche pozmienialem, przepisalem, zastosowalem twoje uwagi i dziala ;)
Jak beda jakies problemy to jeszcze napisze, bo na pewno na tym nie koniec :)


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

Czy moge pobierac tekst w taki sposob?

Kopiuj
LPWSTR buff = L"";
::GetWindowText(g_hWnd,buff,::GetWindowTextLength(g_hWnd));
return std::wstring(buff);

czy lepiej zrobic LPWSTR buff[512]; ?

I jesli mozna to prosze wytlumaczyc dlaczego inaczej a nie tak ;) Bylbym wdzieczny.


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

Musi być tablica, ale nie LPWSTR[], tylko WCHAR[]. Wszystko co ma na początku LP jest wskaźnikiem.

TheAifam5
  • Rejestracja:ponad 12 lat
  • Ostatnio:około 6 lat
  • Postów:127
0

Witam ponownie. Jak utworzyc okno nie blokujac calej aplikacji? Czy zostalo mi tylko stworzenie watku a w nim:

Kopiuj
while (GetMessage(&g_msg, NULL, 0, 0))
	{
		TranslateMessage(&g_msg);
		DispatchMessage(&g_msg);
	}

Hmm?


Wole programowac niz spac :)
Bartosz Wójcik
PeekMessage, ale chyba nie o to Ci chodzi
06
  • Rejestracja:prawie 20 lat
  • Ostatnio:około rok
  • Postów:2440
0

Sama pętla nie wystarczy, okno też musi być stworzone w wątku.

Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 10 godzin
0
Kopiuj
LPWSTR buff[256]; // musi być rozmiar tablicy!
::GetWindowText(g_hWnd,buff,ARRAYSIZE(buff)); // i tu podajemy rozmiar tej tablicy
return std::wstring(buff);

Jak utworzyc okno nie blokujac calej aplikacji? Czy zostalo mi tylko stworzenie watku a w nim:

Dziwny pomysł. Co chcesz właściwie osiągnąć? Mieć kilka okien na raz? (bez problemu, robisz kilka razy CreateWindow, a pętlę jedną). Mieć okno i jakąś operację działającą w tle? (to ta operacja powinna być w osobnym wątku).

TheAifam5
Hmm.. Np, Tworze okno, inicjuje je i wykonuje funkcje Show() - ta funkcja mialaby nie blokowac calej aplikacji, natomiast ShowModal() - miala by blokowac.
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)