Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - Cambiare lo stile di una finestra in win32
Forum - C/C++ - Cambiare lo stile di una finestra in win32

Avatar
AldoBaldo (Member)
Guru


Messaggi: 699
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 12:47
Domenica, 05/11/2017
Buongiorno carissimi

Per un programmino di visualizzazione d'immagini che intendo usare a scuola, mi son trovato nella necessità di predisporre il passaggio dalla visualizzazione nella classica finestra "overlapped" di win32 a quella a schermo pieno. Per farlo ho dovuto affrontare un terreno per me ignoto, approntando un ulteriore programmino di "sperimentazione". Come al solito, le cose sembrano funzionare a dovere, ma io sono un tipo sospettoso. Eccomi quindi qui a chiedere ai "capoccioni" tra voi se quel che ho fatto è sensato oppure no. In caso lo fosse, mi piacerebbe aggiungere il programmino di prova alla sezione "esempi" di pierotofy.it. Che ne dite, lo faccio? Non serve a niente? Devo andare a nascondermi?

Codice sorgente - presumibilmente C#

  1. /*==============================================================================
  2. INFORMAZIONI (FORSE) UTILI
  3.  
  4. 00000000 11001111 00000000 00000000 // WS_OVERLAPPEDWINDOW in binario
  5. 10000000 00000000 00000000 00000000 // WS_POPUP in binario
  6.  
  7. valori restituiti da GetWindowLong( hwnd, GWL_STYLE ):
  8.  
  9. 00010100 11001111 00000000 00000000 // lancio con WS_OVERLAPPEDWINDOW
  10. 10010100 00000000 00000000 00000000 // dopo la modifica con WS_POPUP
  11.  
  12. 10010100 00000000 00000000 00000000 // lancio con WS_POPUP
  13. 00010100 11001111 00000000 00000000 // dopo la modifica con WS_OVERLAPPEDWINDOW
  14.  
  15. flag apparentemente aggiunte da CreateWindow():
  16.  
  17. 00010100 00000000 00000000 00000000
  18. ==============================================================================*/
  19.  
  20. #include <windows.h>
  21.  
  22. const char *kStrNomeClasseProg = "schermopienoenon_class";
  23. const char *kStrTitoloFP = "Schermo pieno e non";
  24. DWORD kStileInizFP = WS_OVERLAPPEDWINDOW; // volendo, provare anche con WS_POPUP
  25. BOOL kFPHaMenu = FALSE;
  26. const int kWInizFP = 640;
  27. const int kHInizFP = 480;
  28.  
  29. HINSTANCE gHInst = NULL;
  30.  
  31. LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wPar, LPARAM lPar );
  32. bool RegistraClasse();
  33. bool CreaFinestraPrincipale( HWND *hwnd, int mostra );
  34.  
  35. int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPInst, LPSTR cmdLn, int show ) {
  36.     HWND hwnd = NULL;
  37.  
  38.     gHInst = hInst;
  39.  
  40.     if( !RegistraClasse() ) return 1;
  41.  
  42.     if( !CreaFinestraPrincipale(&hwnd,show) ) return 2;
  43.  
  44.     MessageBox( hwnd,
  45.                "Premi \"S\" per la finestra a schermo pieno. \n"
  46.                "Premi \"F\" per la finestra standard di Windows. ",
  47.                kStrTitoloFP, MB_ICONINFORMATION );
  48.  
  49.     MSG msg = {0};
  50.  
  51.     while( GetMessage(&msg,NULL,0,0) > 0 ) {
  52.         TranslateMessage( &msg );
  53.         DispatchMessage( &msg );
  54.     }
  55.  
  56.     return 0;
  57. }
  58.  
  59. /*==============================================================================
  60. Con questa funzione la finestra hwnd viene impostata a schermo pieno in stile
  61. WS_POPUP oppure nella visualizzazione "classica" in stile WS_OVERLAPPEDWINDOW.
  62. E' preferibile che lo stile della finestra al lancio del programma sia
  63. WS_OVERLAPPEDWINDOW. In caso contrario, la finestra "classica" verra' collocata
  64. alle coordinate 10,10, con dimensioni 640x480 (window rect, non client rect!).
  65. Il parametro popup sia true per passare alla visualizzazione a schermo pieno,
  66. false per passare alla visualizzazione "classica".
  67. ==============================================================================*/
  68.  
  69. void CambiaStileFinestra( HWND hwnd, bool popup ) {
  70.     // static, per conservare il rect precedente della finestra "classica"
  71.     static RECT gRFin = { 10, 10, 650, 490 };
  72.  
  73.     DWORD stile = GetWindowLong( hwnd, GWL_STYLE );
  74.     RECT r;
  75.  
  76.     if( popup ) {
  77.         if( !(stile&WS_OVERLAPPEDWINDOW) )
  78.             return;
  79.  
  80.         GetWindowRect( hwnd, &gRFin ); // conserva il rect corrente
  81.  
  82.         stile = (stile&(~WS_OVERLAPPEDWINDOW)) | WS_POPUP;
  83.  
  84.         LONG ws = GetSystemMetrics(SM_CXSCREEN);
  85.         LONG hs = GetSystemMetrics(SM_CYSCREEN);
  86.         SetRect( &r, 0, 0, ws, hs );
  87.         AdjustWindowRect( &r, stile, FALSE );
  88.         OffsetRect( &r, (ws-(r.right-r.left))/2, (hs-(r.bottom-r.top))/2 );
  89.     }
  90.     else {
  91.         if( (stile&WS_OVERLAPPEDWINDOW) )
  92.             return;
  93.  
  94.         CopyRect( &r, &gRFin ); // recupera il rect precedente
  95.  
  96.         stile = (stile&(~WS_POPUP)) | WS_OVERLAPPEDWINDOW;
  97.     }
  98.  
  99.     SetWindowLong( hwnd, GWL_STYLE, stile );
  100.     MoveWindow( hwnd, r.left, r.top, r.right-r.left, r.bottom-r.top, TRUE );
  101. }
  102.  
  103. LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wPar, LPARAM lPar ) {
  104.     switch( msg ) {
  105.         case WM_KEYDOWN:
  106.             if( wPar=='S' || wPar=='F' )
  107.                 CambiaStileFinestra( hwnd, wPar=='S' );
  108.             else if( wPar == VK_ESCAPE )
  109.                 SendMessage( hwnd, WM_CLOSE, 0, 0 );
  110.             break;
  111.  
  112.         case WM_CLOSE:
  113.             PostQuitMessage( 0 );
  114.             break;
  115.  
  116.         default:
  117.             return DefWindowProc( hwnd, msg, wPar, lPar );
  118.     }
  119.  
  120.     return 0;
  121. }
  122.  
  123. bool RegistraClasse() {
  124.     WNDCLASS wc      = {0};
  125.     wc.lpfnWndProc   = WndProc;
  126.     wc.hInstance     = gHInst;
  127.     wc.hCursor       = LoadCursor( NULL, IDC_ARROW );
  128.     wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
  129.     wc.lpszClassName = kStrNomeClasseProg;
  130.  
  131.     return RegisterClass( &wc ) != 0;
  132. }
  133.  
  134. bool CreaFinestraPrincipale( HWND *hwnd, int mostra ) {
  135.     RECT rFin;
  136.     LONG margine;
  137.     bool popup = kStileInizFP == WS_POPUP;
  138.  
  139.     if( popup ) {
  140.         LONG ws = GetSystemMetrics(SM_CXSCREEN);
  141.         LONG hs = GetSystemMetrics(SM_CYSCREEN);
  142.         SetRect( &rFin, 0, 0, ws, hs );
  143.         margine = 0;
  144.     }
  145.     else {
  146.         SetRect( &rFin, 0, 0, kWInizFP, kHInizFP );
  147.         margine = 10;
  148.     }
  149.  
  150.     if( FALSE == AdjustWindowRect(&rFin,kStileInizFP,kFPHaMenu) )
  151.         return false;
  152.  
  153.     OffsetRect( &rFin, -rFin.left+margine, -rFin.top+margine );
  154.  
  155.     HWND hwndTmp = CreateWindow(
  156.         kStrNomeClasseProg, kStrTitoloFP, kStileInizFP, rFin.left, rFin.top,
  157.         rFin.right-rFin.left, rFin.bottom-rFin.top, 0, 0, gHInst, NULL );
  158.  
  159.     if( hwndTmp != NULL ) {
  160.         ShowWindow( hwndTmp, mostra );
  161.         *hwnd = hwndTmp;
  162.         return true;
  163.     }
  164.  
  165.     return false;
  166. }


Ultima modifica effettuata da AldoBaldo il 05/11/2017 alle 15:03


ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.
PM Quote
Avatar
Mikelius (Member)
Expert


Messaggi: 525
Iscritto: 14/04/2017

Segnala al moderatore
Postato alle 12:56
Lunedì, 06/11/2017
Ma, se hai tempo, perchè non crei una guida per le GUI in c/c++???
Per quanto riguarda le GUI sono a 0 (tranne un pò con windows form e WPF con c#)

Ho provato il programa, a me sembra un semplice, massimizzare la finestra, sbaglio?

PM Quote
Avatar
AldoBaldo (Member)
Guru


Messaggi: 699
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 16:48
Lunedì, 06/11/2017
Non proprio, perché cambia anche lo stile della finestra da WS_OVERLAPPEDWINDOW (con barra del titolo, ridimensionabilità, bordi, ecc.) a WS_POPUP (un semplice riquadro "fisso" senza titolo né bordo alcuno). Per farlo, per la prima volta nella mia vita ho usato GetWindowLong() e SetWindowLong(), spingendomi su un terreno per me inesplorato.

In merito alla guida, non ho le certezze che servirebbero per "guidare", perché spesso mi ritrovo io stesso a dover essere guidato (o, almeno, mi sento spesso nella posizione di dover ricevere conferme). Senza contare che le API che uso sono ferme a una ventina d'anni fa! Sembra una cosa folle, ma l'ultima documentazione completa e disponibile in blocco unico e ben strutturato da scaricare offline sulla quale son riuscito a mettere le mani è quella di Windows 98; da lì in avanti la documentazione sembra essersi fatta frammentaria e disorganica. Diciamo che sarebbe una bella cosa che venisse riscritto il tutto in un corpo unico, eliminando doppioni, rimandi, integrazioni... , e che si pubblicasse un bel corpo compatto di informazioni monolitiche in versione scaricabile. Invece in Microsoft sembra si stiano dando un gran da fare per generare sempre più confusioni e ambiguità, sovrapponendo questo a quello senza riordinare nulla, il tutto rigorosamente sul web, che è per definizione quanto di più "volatile" esista. O magari sono io che non sono in grado di orientarmi per limiti miei.

Ultima modifica effettuata da AldoBaldo il 06/11/2017 alle 16:49


ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.
PM Quote
Avatar
Roby94 (Member)
Guru


Messaggi: 1170
Iscritto: 28/12/2009

Segnala al moderatore
Postato alle 17:41
Lunedì, 06/11/2017
Aldo, posso chiederti quali sono le motivazioni che ti hanno portato a scegliere l'implementazione "nativa" di Windows per la IU e non una basata su un framework come Qt o wxWidgets?

PM Quote
Avatar
Template (Member)
Pro


Messaggi: 177
Iscritto: 09/12/2015

Segnala al moderatore
Postato alle 19:38
Lunedì, 06/11/2017
Testo quotato

Postato originariamente da AldoBaldo:

  Invece in Microsoft sembra si stiano dando un gran da fare per generare sempre più confusioni e ambiguità, sovrapponendo questo a quello senza riordinare nulla



Sarebbe demenziale, dal punto di vista della Microsoft, ri-ordinare informazioni ormai inutili per la stragrande maggioranza dei programmatori software "high-level": avendo implementato MFC, ATL e più recentemente il framework .Net, l'utilizzo delle "vecchie" API non ha più senso in molti casi.
Considera inoltre che la Microsoft sta puntando, almeno per quanto ne so io, sulle nuove API WinRT, già introdotte in Windows 8 e disponibili per l'estensione proprietaria del C++, per i linguaggi .Net e (ORRORE) per quella merda indicibile che è Javascript.

Ultima modifica effettuata da Template il 06/11/2017 alle 19:41
PM Quote
Avatar
lumo (Member)
Expert


Messaggi: 449
Iscritto: 18/04/2010

Segnala al moderatore
Postato alle 23:40
Lunedì, 06/11/2017
Beh la microsoft ha tirato fuori un'infinità di tecnologie per le GUI in windows, almeno in genere ha sempre mantenuto la retrocompatbilità.
Mi dispiace solo per i poveretti che hanno dovuto sviluppare per windows phone.
Non so niente di windows quindi non so giudicare il codice, comunque non mi sembra troppo complicato, il commento iniziale è un po' ad cazzum (nel senso che è decontestualizzato), per il resto direi caricalo pure.

Ultima modifica effettuata da lumo il 06/11/2017 alle 23:42
PM Quote
Avatar
Mikelius (Member)
Expert


Messaggi: 525
Iscritto: 14/04/2017

Segnala al moderatore
Postato alle 0:08
Martedì, 07/11/2017
Testo quotato

Postato originariamente da AldoBaldo:

Non proprio, perché cambia anche lo stile della finestra da WS_OVERLAPPEDWINDOW (con barra del titolo, ridimensionabilità, bordi, ecc.) a WS_POPUP (un semplice riquadro "fisso" senza titolo né bordo alcuno). Per farlo, per la prima volta nella mia vita ho usato GetWindowLong() e SetWindowLong(), spingendomi su un terreno per me inesplorato.

In merito alla guida, non ho le certezze che servirebbero per "guidare", perché spesso mi ritrovo io stesso a dover essere guidato (o, almeno, mi sento spesso nella posizione di dover ricevere conferme). Senza contare che le API che uso sono ferme a una ventina d'anni fa!...



Si, ora noto le piccole differenze.

Per la guida, la cosa buona delle guide a differenza degli articoli e che puoi iniziare a scriverla oggi, poi prima di pubblicarla puoi aspettare che qualche anima pia la legga e al limite ti avvisi di imprecisioni, oppure può scrivere direttamente un capitolo per una specifica API. Il fatto che sia di 20 anni fa rende reperire la documentazione più difficile, quindi più importante scriverla rispetto ad una sul  C# 6, ad esempio.
Anche se come detto da altri, guide su MFC , ATL, GTK+, Qt ecc. ecc. sarebbero più attuali e forse utili.

PM Quote
Avatar
AldoBaldo (Member)
Guru


Messaggi: 699
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 9:09
Martedì, 07/11/2017
Roby94: "Aldo, posso chiederti quali sono le motivazioni che ti hanno portato a scegliere l'implementazione "nativa" di Windows per la IU e non una basata su un framework come Qt o wxWidgets?"

Perché tempo fa ho impiegato un sacco di tempo a imparare quella e sono un abitudinario (leggo le targhette sugli ascensori, ecc. - cit.). In più predisporre i progetti per librerie mi dà un sacco di grattacapi per limiti miei. Poi c'è il fatto che ogni tre per due quelle librerie cambiano, e quell'altro fatto che per aprire una finestra che ti fa "ciao" a volte generano eseguibili da millemila mega e, nei casi peggiori, che richiedono pure una fila di .dll (che, ovviamente, devono essere della versione giusta, nel posto giusto, al momento giusto, ecc.).

Insomma, perché tendo a fare sempre le stesse cose e poi mi ci affeziono.


ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.
PM Quote
Avatar
AldoBaldo (Member)
Guru


Messaggi: 699
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 9:11
Martedì, 07/11/2017
Lumo, sulla questione della retrocompatibilità, in effetti, Microsoft è stata FIN'ORA encomiabile. Spero proprio che continui così almeno su quel versante.


ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.
PM Quote