Σάββατο, 1 Οκτωβρίου 2011

Visual C++ MFC: how to...

Δεν σου έχει τύχει (εμένα πολλές φορές) να ψάχνεις μια πληροφορία και να μην το βρίσκεις; Να ανοίγεις βιβλία, να ανατρέχεις στο διαδίκτυο και πάλι να αναλώνεις χρόνο πολύ, για να το βρεις;  Στην Visual C++ αυτό μοιάζει να είναι κανόνας. Τόσα ξενόγλωσσα εγχειρίδια (δεν μιλώ για ελληνικά - κανείς δεν ασχολείται) και κανένα δεν καλύπτει το θέμα πλήρως. Υποχρεώνεσαι και ανατρέχεις στο MSDN της Microsoft. Καλό ιστολόγιο, δεν λέω, αλλά πρέπει να κάνεις πολλά κλικ και η πληροφορία είναι ελλιπής. 

Επειδή, λοιπόν, ψάχνω, ψάχνω και ψάχνω και καταναλώνω χρόνο, για να βρω το αποτέλεσμα, θέλω να το αναρτώ κιόλας, μήπως σώσω τον πολύτιμο χρόνο κάποιου άλλου ταλαίπωρου. Ιδού:


Πώς χρησιμοποιούμε ένα bitmap σε ένα κουμπί (how to set a bitmap on a button):

how to set a bitmap on a button


Πώς δημιουργούμε ένα tool tip σε ένα κουμπί (how to create a button tool tip):
how to create a button tool tip



Πώς αλλάζουμε το εικονίδιο εφαρμογής Visual C++ MFC (how to change MFC application icon):
Για να αλλάξουμε το εικονίδιο μιας εφαρμογής Visual C++ MFC:

1. Τοποθετούμε το νέο εικονίδιο στον φάκελο Resources.
2. Πηγαίνουμε Solution Explorer > [appname].rc
3. Δεξί κλικ > View Code,  βρίσκουμε την γραμμή 

 IDR_MAINFRAME ICON    "res\\[new icon].ico"

αλλάζουμε το όνομα του εικονιδίου δίνοντας αυτό του νέου.

Για να αλλάξουμε το εικονίδιο MFC στο Ribbon, φορτώνουμε και πάλι το αρχείο *.rc και στα bitmap αναζητούμε το IDB_MAIN το οποίο και αλλάζουμε με το εικονίδιο της επιλογής μας.




Πώς αλλάζουμε το «Untitled- My Application» στον τίτλο της εφαρμογής Visual C++ MFC (how to change Untitled- My Application title):

Στον τίτλο του κυρίως παραθύρου (frame) του προγράμματος, από προεπιλογής εμφανίζονται το document nameApplication name. Όταν δεν έχει ακόμη φορτωθεί κανένα document, τότε εμφανίζεται το untitle1.



ΑΠΕΝΕΡΓΟΠΟΙΗΣΗ ΤΟΥ DOCUMENT NAME

·         Override CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

·         Πρόσθεσε το cs.style &= ~FWS_ADDTOTITLE;

Το cs είναι τύπου CREATESTRUCT και περιέχει την member data style. Με την παραπάνω εντολή αφαιρούμε την τιμή FWS_ADDTOTITLE, όπου FWS σημαίνει FrameWindowStyle.


ΑΛΛΑΓΗ ΤΟΥ DOCUMENT NAME ΜΕ ΚΩΔΙΚΑ
Ο κώδικας μπορεί να κληθεί και από την View και είναι ο ακόλουθος:

C[appname]Doc* pDoc = GetDocument();
pDoc->SetTitle(L”Ο νέος τίτλος”);

ΑΛΛΑΓΗ ΤΟΥ APPLICATION NAME ΜΕ ΚΩΔΙΚΑ
Το application name αποθηκεύεται σε ένα protected member data ονόματι m_strTitle της κλάσης CMainFrame. Για να το αλλάξουμε, δημιουργούμε μία νέα μέθοδο:

CMainFrame::SetAppName(LPCTSTR title)
{
                                m_strTitle = title;
}

Η συγκεκριμένη συνάρτηση μπορεί να κληθεί από το View ως εξής:

            CMainFrame* pFrame = static_cast(GetParent());   
                pFrame -> SetAppName(L”Το δικό μου όνομα”);
                pFrame -> OnUpdateFrameTitle(true);

Το static_cast μπαίνει, διότι η GetParent() καλεί το μητρικό παράθυρο (δηλ. το frame) που είναι τύπου CWnd*. Ο pointer που βλέπει στο μητρικό αντικείμενο μπορεί να δει και στο θυγατρικό.

ΜΟΝΙΜΗ ΑΛΛΑΓΗ ΤΟΥ APPLICATION NAME
Στο αρχείο resource .rc βρίσκουμε την ακόλουθη γραμμή, όπου αλλάζουμε το όνομα:

STRINGTABLE
BEGIN
    AFX_IDS_APP_TITLE       "Client Manager"
    AFX_IDS_IDLEMESSAGE     "Έτοιμο"
END


Πώς δημιουργούμε ένα Modeless παράθυρο διαλόγου (how to create a modeless dialog box):
To modeless παράθυρο διαλόγου πρέπει να ορισθεί στο CView ή γενικά στο frame, ώστε να μην παραμείνει ξεκρέμαστος, αν κλείσει το παράθυρο που τον κάλεσε.
Επίσης, πρέπει να φορτωθεί στην μνήμη heap (Η μνήμη heap (ή δυναμικής τοποθέτησης μνήμη) είναι η μνήμη όπου αποθηκεύονται μεταβλητές κατά την διάρκεια του χρόνου εκτέλεσης (runtime))  με εντολή new και όχι στην stack(Η μνήμη stack είναι η μνήμη, στην οποία αποθηκεύονται μεταβλητές όταν δηλώνονται ή αρχικοποιούνται, πριν την εκτέλεση (runtime), ώστε να εξακολουθεί να υπάρχει, ακόμη κι αν καταργηθεί η συνάρτηση που την κάλεσε.
Η διαδικασία που ακολουθούμε είναι:

1       Δημιουργούμε το παράθυρο διαλόγου στο μενού Resources.

2      Αντιστοιχούμε στο παράθυρο διαλόγου μία class::CDialog (π.χ. CModeless) και δηλώνουμε τις απαραίτητες memder data.

3   Στην κλάση που θα καλέσει την CModeless δημιουργούμε μία μεταβλητή CModeless*, δηλαδή:
CModeless* pDlg = new CModeless;

Μ’ αυτό τον τρόπο το παράθυρο έχει αποθηκευθεί στην μνήμη heap.

.     Στην κλάση CModeless παρακάμψουμε (override) τις μεθόδους OnOK(), OnCancel() και PostNcDestroy() ως εξής:

void CModeless::OnCancel()
{
                DestroyWindow();
}


void CModeless::OnOK()
{
                DestroyWindow();
}


void CModeless::PostNcDestroy()
{
                delete this;
}

Αυτό γίνεται, διότι στις πρώτες δύο, δεν πρέπει να κληθεί η EndDialog (η οποία καλείτε μόνον σε modal παράθυρα διαλόγων). Στην τρίτη μέθοδο η εντολή delete this καταργεί οριστικά το modeless παράθυρο.
Σημαντική είναι η χρήση της εξής ιδιότητας: ένας pointer τύπου βασικής κλάσης που έχει ορισθεί στην παραγόμενη κλάση μπορεί να δει και την βασική (με static_cast ή με dynamic_cast).


Πώς προσθέτουμε εικονίδια σε μία έτοιμη μπάρα εικονιδίων (τύπου bitmap) για το Ribbon:
Μπορούμε να επεξεργαστούμε μία ήδη έτοιμη μπάρα από εικονίδια τύπου bmp και να προσθέσουμε το δικό μας στο τέλος.
Τα μικρά εικονίδια έχουν μέγεθος 16x16 pixel, ενώ τα μεγάλα εικονίδια 32x32 pixel. Αν η μπάρα έχει 10 εικονίδια, τότε το μέγεθός της είναι 320x32 (για μεγάλα εικονίδια) ή 160x16 (για μικρά εικονίδια).
Η μπάρα μπορεί να φορτωθεί στο Photoshop, όπου και μπορούμε να την επεξεργαστούμε. Αφού μεγαλώσουμε τον καμβά στο νέο μήκος και προσθέσουμε το νέο εικονίδιο, πρέπει να ασχοληθούμε με έναν σημαντικό παράγοντα: το Alpha Channel. Το κανάλι αυτό αφορά στην διαφάνεια της μπάρας. Στην επιλογή Channels, επιλέγουμε το Alpha Channel και σβήνουμε το εσωτερικό του εικονιδίου, ώστε αυτό να είναι ορατό. Έτσι, το μαύρο υπόβαθρο δεν εμφανίζεται, όταν καταχωρήσουμε την μπάρα εικονιδίων στο ribbon.


Πώς κάνουμε reset των settings στο Visual Studio (how to reset settings in Visual Studio):
Μπορούμε να κάνουμε reset στα setting ακολουθώντας την διαδρομή:

Tools > Import & Export Settings

Εκεί μπορούμε να σώσουμε τις τρέχουσες ρυθμίσεις και να επαναφέρουμε τις αρχικές προεπιλογές του προγράμματος.


Πώς κάνουμε reset των settings στο Visual Studio (how to reset settings in Visual Studio):
Το splash screen δεν είναι παρά ένα παράθυρο διαλόγου με χρονοδιακόπτη και χωρίς περίγραμμα και κουμπιά. Η διαδικασία δημιουργίας του είναι η ακόλουθη:


   Δημιουργούμε στα resources ένα νέο παράθυρο διαλόγου. Αφαιρούμε όλα τα κουμπιά, προσθέτουμε μόνον εικόνα και κείμενο. Το παράθυρο δεν πρέπει να έχει system menu, πρέπει να είναι top, να μη έχει border (ή έστω thin) και να εμφανίζεται πάνω από όλα τα υπόλοιπα παράθυρα.
    Δημιουργούμε μία κλάση τύπου CdialogCdialogEx) (π.χ. την CsplashScreen) και την αντιστοιχούμε στο παράθυρο διαλόγου.
      Στην κλάση προσθέτουμε μία μέθοδο Show(UINT millisec = 5000) που στην υλοποίησή της περιλαμβάνει τα ακόλουθα:

                                                                               if(Create(IDD, GetDesktopWindow())
                                                                                {
                                                                                        ShowWindow(SW_SHOW);
                                                                                        SetTimer(1, millisec, NULL);
                                                                                 }

Το 1 στον SetTimer είναι index του Timer (για την περίπτωση που υπάρχουν πολλοί). Την κλήση του Timer, όταν παρέλθει ο χρόνος, την λαμβάνει ένα window message, το WM_Timer.
   Το WM_Timer προστίθεται στην κλάση μας και ορίζει έναν handle εντός του οποίου προσθέτουμε μία εντολή DestroWindow(), ώστε να καταστραφεί το παράθυρο διαλόγου, μετά την πάροδο του χρονικού διαστήματος.
     Τώρα, η splash screen είναι έτοιμη. Δημιουργούμε μία member τύπου CsplashScreen στην κλάση CmainFrame.  Στον constructor της CmainFrame τοποθετούμε την member και εφαρμόζουμε πάνω της την μέθοδο Show, όπου μπορούμε να ορίσουμε τον χρόνο εμφάνισης της splash screen.