Newsgroup: it.comp.programmare.win32
Titolo: aiuto MFC [lungo]

Ritorno con alcune domande, sempre ambiente win32, VC++ 6.0.
Devo fare un dialogo file-open con un controllo in piu'.
Seguendo pedissequamente le indicazioni del Kruglinski (quinta edizione,
pagg 170 e seguenti) ho derivato una classe da CFileDialog, disegnando il
dialogo con un groupbox di id pari a 0x045f e overloadando le opportune
funzioni per gestire il nuovo elemento. Funziona piu' o meno tutto bene.
Prima domanda: quell'0x045f presumo sia un codice di windows per indicare il
dialogo file-open, o qualcosa di simile. Dove trovo una tabella di questi
identificatori?
Seconda domanda. Avendo io settato con SetDialogBkColor(RGB(70, 200, 200)) i
colori di sfondo dei dialoghi (nell'InitInstance dell'applicazione) anche
questo dialogo mi appare con questo colore. Solo che i vari controlli
presenti dentro (es. la piccola toolbar "crea cartella, dettagli ecc.")
usano lo sfondo predefinito. Come posso fare a dire al CFileDialog di usare
lo sfondo da me definito anche per i controlli interni? O, eventualmente,
come posso dire a MyCFileDialog (la classe derivata) di usare lo sfondo
predefinito?
Terza domanda: essendoci un pezzo in piu' la finestra di dialogo si
"allarga" quando viene chiamata. Solo che poi, quando chiamo normalmente
CFileDialog, questa mi rimane di dimensioni "allargate", con un brutto
effetto visivo. Come posso fare a evitare questo inconveniente?
Approfitto di questo msg per una quarta domanda riguardante la stampa.
Cercando con deja ho trovato, su questo ng, un pezzo di codice semplice
semplice per stampare "ciao" sulla stampante, ed ho usato qualcosa di simile
(scusate l'indentazione a cappella e lo stile non propriamente da purista
del c++):
HDC   hDC;
DOCINFO  docInfo;
LPDEVMODE hdm;
DEVMODE  *dm;
int   xres,yres;
char  job_name[400];
CPrintDialog printer_dialog(FALSE, 0);
----------
// in OnInitDialog
    docInfo.cbSize = sizeof(DOCINFO);
    docInfo.lpszDocName = job_name;
    docInfo.lpszOutput = NULL;
    docInfo.lpszDatatype = NULL;
    docInfo.fwType = 0;
    new_printer_selected = 0;
------------
// quando chiudo il dialogo
 GlobalFree(hdm);
    DeleteDC(hDC);
// quando scelgo una nuova stampante
if (printer_dialog.DoModal() == IDOK)
 {
  hDC = printer_dialog.GetPrinterDC();
     hdm = printer_dialog.GetDevMode();
  dm = (DEVMODE *)GlobalLock(hdm);
  xres = dm->dmPrintQuality;
  yres = dm->dmYResolution;
  GlobalUnlock(hdm);
  new_printer_selected = 1;
 }
--------------
// quando stampo
 if (!new_printer_selected)
 {
  printer_dialog.GetDefaults();
  hDC = printer_dialog.GetPrinterDC();
  hdm = printer_dialog.GetDevMode();
     dm = (DEVMODE *)GlobalLock(hdm);
     xres = dm->dmPrintQuality;
  yres = dm->dmYResolution;
  GlobalUnlock(hdm);
 }
    StartDoc(hDC,&docInfo);
     stampa_singola_scheda();
    EndDoc(hDC);
-----------------
// funzione per stampare
void CStaschedDlg::stampa_singola_scheda()
{
CFont font;
CBrush brush;
 switch(tipo_pallino)
 {
  case 0: brush.CreateSolidBrush(RGB(0, 0, 0));
    break;
  case 1: brush.CreateHatchBrush(HS_DIAGCROSS, RGB(0, 0, 0));
    break;
  case 2: brush.CreateHatchBrush(HS_CROSS, RGB(0, 0, 0));
    break;
 }
 font.CreateFont(12, 8, 2700, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH |
FF_ROMAN, NULL);
 StartPage(hDC);
 SetMapMode(hDC, MM_LOENGLISH);
  stampa_scheda(brush, font);
 EndPage(hDC);
}
void CStaschedDlg::stampa_scheda(CBrush &br, CFont &fn)
{
int  i, j;
HGDIOBJ p;
 p = SelectObject(hDC, HBRUSH(br));
....
       Ellipse(hDC,
        (int)(50 + margine_sx + 18.18 * (2 * i + j / 16) -
dimensione_pallino / 2),
        - (int)((50 + margine_alto + 16.273 * (j % 16)  - dimensione_pallino
/ 2)),
        (int)(50 + margine_sx + 18.18 * (2 * i + j / 16) +
dimensione_pallino / 2),
         - (int)((50 + margine_alto + 16.273 * (j % 16)  +
dimensione_pallino / 2))
        );
....
 SelectObject(hDC, p);
 p = SelectObject(hDC, HFONT(fn));
    TextOut(hDC,
     (int)(50 + margine_sx + 18.18 * 12.0 - 0),
     - (int)((50 + margine_alto + 16.273 * 15.0)),
     titolo_scheda, strlen(titolo_scheda));
....
 SelectObject(hDC, p);
}
I problemi sono diversi (ma due sono "gravi").
Primo: se seleziono prima il font (e stampo il titolo) e poi il brush (e
stampo il pallino) non funziona. La cosa strana e' che, facendo puntare hDC
al DC di una finestra qualsiasi, sul monitor funziona benissimo. Ma quando
hDC e' l'handle della stampante no. Vuole prima il brush e poi il font.
Dove sbaglio?
Secondo: la stampa funziona. Ma se la richiamo una seconda volta mi butta
fuori il foglio senza nulla. Presumo di non aver rilasciato qualche risorsa,
ma non so proprio dove mettere le mani (il codice deriva direttamente da un
msg che ho trovato con deja, e io non so nulla di come si stampi in
windows).
Dov'e' che non funziona?
Domanda: l'ultimo SelectObject che faccio, serve o no? (subito dopo sono
sicuro che viene un EndPage, ma non un EndDoc)
Domanda: il SetMapMode lo posso mettere una volta solo dopo StartDoc o devo
metterlo sempre, ad ogni StartPage?
Mi scuso per la lunghezza e ringrazio in anticipo.
Marco Fabiani

 metterlo sempre, ad ogni StartPage?
Devi metterlo sempre. E devi anche riselezionare tutti gli oggetti, e in
generale 'reinizializzare' il DC.
--
Bye! Lorenzo Lutti
http://www.geocities.com/SiliconValley/Peaks/6258/

testo?
Provero'.
Scusate ma approfitto per altre domande (VC++ 6.0, MFC).
Devo fare un dialoghino con 180 check-box (non chiedetemi perche').
Potrei fare tutto con l'editor di risorse, ma poi devo scrivere 180 righe
del tipo DDX/DDV.
Sarebbe piu' comodo fare, in DoDataExcange, quacosa del tipo
    for (i = 0; i < 180; i++)
        DDX_Check(pDX, IDC_PRIMO_BOTTONE + i, s[i]);
solo che non funziona. O meglio, non credo di poter essere sicuro del fatto
che gli identificatori IDC_PRIMO_BOTTONE1, IDC_PRIMO_BOTTONE2 ecc. siano
#defined con valori progressivi (ho provato, e a volte capita). (Domanda: e'
possibile (a meno di ridefinire "a mano") forzare il resource editor a
mettere gli id con valori progressivi?)
Quindi cerco di farli "a mano" in OnInitDialog.
Devo posizionare i bottoni in un groupbox, quindi mi occorre di sapere la
posizione del groupbox rispetto al dialogo. (domanda: come prendo il primo
ID libero? Io parto sempre da 2-3000, ma c'e' un modo "standard", del tipo
WM_USER per capirci?)
E qui casca l'asino (cioe' io): non ho trovato, ne' in MFC ne' nell'SDK un
metodo per avere la posizione di una finestra rispetto alla finestra padre.
GetWindowRect mi da' il rect rispetto allo schermo (ma del window, quindi
anche del title bar). Anche facendo le differenze tra la windowrect del
padre e del figlio mi rimane il titlebar di mezzo, quindi non riesco a
mettere i bottoni dove dico io. GetClientRect mi da' solo le dimensioni.
GetWindowPlacement non fa al caso mio (almeno credo).
Eppure, quando (qualcuno dovra' farlo!) si chiama la Create del group box
bisognera' dargli la posizione, rispetto al padre! Dove sono queste
informazioni?
Grazie in anticipo.
Marco

 GetWindowPlacement non fa al caso mio (almeno credo).
Perche` no?
Alex

Perche` no?
Perche' mi da' la posizione della window (col titlebar). Se invece gli
chiedo la posizione del workspace me la fa partire da 0, 0.
Almeno, a leggere sull'MSDN ho capito cosi'. Comunque ci provo.
Marco

 anche del title bar).
Come API c'e` ScreenToClient(). Per un rettangolo lo devi chiamare due volte,
ma poco male. Usando MFC, invece, lo puoi fare direttamente con un rettangolo,
c'e` la relativa funzione membro in CWnd.


Come API c'e` ScreenToClient().
Credo proprio che sia la soluzione al mio problema.
Grazie mille.
Marco
PS: hi rifatto la stampa e ora funziona. Evidentemente non (dis)allocavo
qualcosa, o tra una stampa e l'altra riallocavo qualcosa che non dovevo
riallocare.