Newsgroup: it.comp.programmare.win32
Titolo: Gestire le viste

Vorrei creare 5 finestre, associare ad ognuna un proprio nome fisso, e ogni
volta che č richiesto disegnare solo sulla finestra opportuna (che posso
ritrovare con il nome). Le finestre vengono create cosě
BOOL CSchedulingDoc::OnNewDocument()
{
 if (!CDocument::OnNewDocument())
  return FALSE;
for( int i = 0 ; i < 4 ; i ++ )
 {
  CChildFrame * newFrame = ( CChildFrame * )theApp.m_pDocTemplate ->
CreateNewFrame( this ,
reinterpret_cast< CFrameWnd * > ( GetFrameStyle() ) ) ;
  InitialiseNewFrames(i);   // in questa funzione ciclo su tutte le viste
attive (1..2....) e metto SetScrollSize()
// se non faccio cosě MFC asserte dicendo che una CScrollView prima di
essere disegnata ha bisogno
// di sapere il valore dello scroll --> posso fare di meglio?
      newFrame -> ShowWindow( SW_MINIMIZE ) ;
      newFrame -> UpdateWindow() ;
     }
 SetFramesText(); // io pensavo che qui potessi inizializzare le mie
finestre --> vedi funzione sotto
    return TRUE;
}
void CSchedulingDoc::SetFramesText()
{
POSITION pos = GetFirstViewPosition();
 int i = 1;
 while (pos)
 {
  CSchedulingView* pView = (CSchedulingView*) GetNextView( pos );
   switch (i)
      {
          case 0: pView ->SetWindowText("DIRETTO");
          case 1: pView ->SetWindowText("DURATA MINIMA");
          case 2: pView ->SetWindowText("RISORSE MINIME");
          case 3: pView ->SetWindowText("MINIMO (RISORSE*DURATA)");
        case 4:pView->SetWindowText("DURATA MASSIMA");
      }
     i++;
 }
}
risultato? tutte le finestre sono senza titolo, a parte la prima, quella di
"default"!
Ovvero questa funzione non produce alcun effetto. Come mai?


SetWindowText() non ti conviene qua.  Devi creare un ovverride
OnUpdateFrameTitle() di CChildFrame per poter controllare direttamente i
titoli delle finestre "child".  Forse ti converrebbe anche aggiungere
CString m_Titolo alla classe CChildFrame.

Scusa ma non ho capito. Su msdn dice:
COleClientItem::OnUpdateFrameTitle
virtual BOOL OnUpdateFrameTitle( );
Remarks
Called by the framework during in-place activation to update the frame
window's title bar. The default implementation does not change the frame
window title. Override this function if you want a different frame title for
your application, for example "server app - item in docname" (as in,
"Microsoft Excel - spreadsheet in REPORT.DOC"). This is an advanced
overridable.
ma il mio doc è derivato da CDocument e CChildFrame da CMDIChildWnd....(non
vorrei complicarmi ulteriormente la vita, almeno finchè non ho imparato le
cose di base)
Comunque il problema è un'altro, forse non sono stato chiaro. Il fatto che
ogni finestra abbia un suo titolo è importante per l'utente ma è un
dettaglio. Il fatto è come io possa riferirmi ad ogni finestra quando questa
viene ridimensionata, chiusa, quando viene selezionata con il mouse ecc,
cioè come faccio a sapere qual'è la finestra?
Il fatto è che io, comunque, ho una sola classe documento e una sola classe
vista!
Comunque vorrei essere più chiaro su ciò che devo fare:
La mia applicazione risolve lo scheduling di n job usando 5 tipi di
risolutore diversi. Io vorrei avere 5 finestre inizialmente minimizzate che
hanno come titolo il nome del risolutore, quando un utente ha usato quel
risolutore la "sua" finestra e soltanto quella disegna il risultato e così
via per tutti gli altri risolutori. Quindi come faccio ad identificare la
finestra su quale disegnare? Inoltre quando viene generato OnDraw(), magari
per tutte e 5 le finestre, devo ridisegnare quella giusta! Per fare questo
pensavo che fosse semplice dare un titolo ad ogni finestra e quando viene
generato OnDraw ciclare fra tutte le finestre e ridisegnare soltanto quelle
che hanno il titolo di un risolutore che l'utente ha già usato. (Se poi per
ritrovare una finestra c'è un modo migliore che non andare a vedere il suo
titolo, sarebbe anche meglio...)
P.S. Altrimenti torno indietro e genero una sola finestra. Il fatto è che a
me andava benissimo un programma SDI solo che all'inizio dissi, vabbè per
essere più generale usiamo un prog. MDI ! (potessi tornare a 15 giorni
fa....)

 Scusa ma non ho capito. Su msdn dice:
Aggiungi il seguente al file CChildFrm.cpp:
void CChildFrame::OnUpdateFrameTitle(BOOL bAddToTitle)
{
    SetWindowText( "Dave's Window" ) ;
}
e poi
 void OnUpdateFrameTitle(BOOL bAddToTitle);
al file CChildFrm.h.
Adesso, le finestre vengono create cosi':
 for( int i = 0 ; i < 5 ; i ++ )
 {
  CChildFrame * newFrame = ( CChildFrame * )theApp . m_pDocTemplate ->
CreateNewFrame( this , reinterpret_cast< CFrameWnd * > ( GetFrameStyle() ) )
;
  newFrame -> ShowWindow( SW_SHOWNORMAL ) ;
  newFrame -> UpdateWindow() ;
  newFrame -> OnUpdateFrameTitle( FALSE ) ;
 }


avevo pensato di passare a OnUpdateFrameTitle l'indice i del ciclo, e in
base a quello assegnare il titolo. Ma evidentemente è una c.... (cioè
OnUpdateFrameTitle è un override anche se su msdn non lo dice, w quindi non
accetta altri parametri? )
Guarda la schifezza che ho fatto per ridisegnare le finestre ognuna col suo
titolo e disegnare solo su quella giusta:
void CSchedulingView::OnDraw(CDC* pDC)
{
    CMDIFrameWnd* pMDIFrame = (CMDIFrameWnd*)AfxGetMainWnd();
    HWND hwndT;
     CChildFrame* pFrame = (CChildFrame*) GetParentFrame();
     int k;
     int myID = pFrame->GetDlgCtrlID();  <-- ho notato che tutte le volte
gli ID sono sempre gli stessi !!!
// ma come è possibile? penso sia una cosa "orrenda" fare così ma è l'unico
modo che ho trovato...
// ma poi sul mio computer gli ID sono sempre quelli, ma su un'altro
computer che succederebbe?
      hwndT=::GetWindow(pMDIFrame->m_hWndMDIClient, GW_CHILD); <-- questo
l'ho trovato in un codice
     if (hwndT == NULL) AfxMessageBox("NULL");
     else
     {  // quindi a seconda dell' ID riconosco la finestra
          TCHAR szWndTitle[256];
          switch (myID)
      {
          case 65280: ::SetWindowText(hwndT,"DIRETTO");
               k = 0;
               break;
          case 65281: ::SetWindowText(hwndT,"DURATA MINIMA");
               k = 1;
               break;
          case 65282: ::SetWindowText(hwndT,"RISORSE MINIME");
               k = 2;
               break;
    }
quindi io ho una lista[6] di Record in cui lo scheduling del risolutore 0 è
memorizzato in posizione 0, lo scheduling del risolutore 1 è memorizzato in
posizione 1, ecc.. e l'indice k è appunto l'indice di lista[k]
Ovvero in pratica questo "tremendo" codice funziona ma mi sembra di
camminare sulle braci...
Inoltre il titolo viene si ridisegnato quando la finestra è attiva, e viene
quindi generato OnDraw(), ma nelle finestre che sono minimizzate il titolo è
" Dave's Window " !
Come posso fare?

Ho rieseguito il debug e  mi sono accorto che forse il problema č tutto in
InitialiseNewFrames, che ho inserito all'interno del ciclo, che viene
richiamata ad ogni ciclo in OnNewDocument, quindi:
BOOL CMviewDoc::OnNewDocument()
{
        for( int i = 0 ; i < 5 ; i ++ )
    {
        CChildFrame * newFrame = ( CChildFrame * )theApp.m_pDocTemplate ->
CreateNewFrame( this , reinterpret_cast< CFrameWnd * > (
GetFrameStyle() ) );
        InitialiseNewFrames() ;    <----- IL PROBLEMA E' QUI
        newFrame -> ShowWindow( SW_SHOWMINIMIZED ) ;
        newFrame -> UpdateWindow() ;
    }
infatti in Initialise c'č questo "stupido" ciclo:
POSITION pos = GetFirstViewPosition() ;
 while( pos != NULL )
 {
  CSchedulingView* pView = reinterpret_cast< CSchedulingView * > (
GetNextView( pos ) ) ;
  CSize docSize;
  docSize = CSize(900,800);
  pView->SetScrollSizes( MM_TEXT, docSize ); // serve questo prima di
richiamare ShowWindow, o no?
quindi ogni precedente vista viene riattivata e viene anche richiamato
CChildFrame::OnUpdateFrameTitle. Quindi il problema ora č molto diverso e
piů circoscritto, devo solo trovare il modo di inizializzare l'ultima
CScrollView senza ciclare su TUTTE!
 Inoltre per dare un titolo alle finestre userei questo metodo (non so come
usare il membro di cui parli...)
void CChildFrame::OnUpdateFrameTitle(BOOL bAddToTitle)
{
     extern ID_WND;
      if (ID_WND == 0)
          SetWindowText( "Dave's Window" ) ;
     if (ID_WND == 1)
          SetWindowText( "Andrea's Window" )


Mi sembra che ci sia quasi arrivato.  Adesso che hai tolto i bug, ci sono
vari modi.  Io preferisco dichiarare un membro di CChildFrame in questo modo
:
CString m_Titolo ;
Poi, quando viene creata la finestra, puoi gestire il titolo come vuoi.
Quindi, tutto questo risulta in una funzione :
 void CChildFrame::OnUpdateFrameTitle(BOOL bAddToTitle)
{
    SetWindowText( m_Titolo ) ;
}

Davvero, c...
Cio' girato intorno da tutte le parti, la soluzione era lì davanti ma non
c'era modo di vederla. Non so se hai letto anche il messaggio precedente,
penso di si anche se non c'erano commenti. Avevo pensato alle soluzioni più
intrigate !
Il fatto è che non sono assolutamente abituato a programmare a oggetti,
l'unica "programmazione" che ho fatto, se così si può chiamare, è stata con
il Pascal con un unico file e centinaia di variabili globali. Poi un po' di
VB e C a tempo perso e ora Vc++, anche questo un po' a tempo perso anche se
credo che d'ora in poi mi servirà abbastanza costantemente.
P.S. Un consiglio, a questo punto mi conviene leggere prima un libro del C++
(non mi ricordo come si chiama l'autore, mi sembra Soustrup, o qualcosa del
genere) e fra l'altro è pesissimo o un libro sulle API di windows e su MFC?
io penso il primo perchè è più generale e non è limitato a windows. Che ne
pensi?


Si chiama "The C++ Programming Language, Special Edition" ~ Bjarne
Stroustrup, ma e' assai difficile leggerlo come un libro.  Pero' se hai
voglia scrivere C++, bisogna che tu sappia il linguaggio.
Forse la cosa migliore sarebbe di leggere un libro di MFC.  Poi, se trovi
qualcosa che non capisci, puoi rincorrere a Stroustrup per controllare.
Questo e' il metodo che io ho usato per imparare MFC (avevo gia' 5 anni di
esperienza con la programazione di Windows pero').
Per imparare MFC, ho usato "Inside Visual C++"  di Kruglinski.  Poi per
programatori piu avanzati c' e' "MFC Internals" di Mary Kirtland e George
Shepherd.
Naturalmente, ci sono sempre i soliti consigli riguardante la programazione
di Windows - cioe' Petzold e Richter.
Non so se tutti questi libri sono disponibili in italiano pero'.