Προς το περιεχόμενο

Προγραμματισμος c(γραφικο περιβαλλον)


LOLgamer

Προτεινόμενες αναρτήσεις

Δεν ειναι μονο τα switch.

Εβαλα ενα button που εμφανιζε μια νεα φορμα και το κοκκινο x (πανω δεξια) δεν εκλεινε τη φορμα. Ηθελε κώδικα ... :mad: :mad:

Χρειάζεται το PostQuitMessage (ως απόκριση στο WM_DESTROY message) και αν το πρόβλημα επιμένει τότε θα πρέπει να δει κανείς μήπως εκ παραδρομής έχει δηλώσει λάθος την GetMessage του.
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

  • Απαντ. 139
  • Δημ.
  • Τελ. απάντηση

Συχνή συμμετοχή στο θέμα

Συχνή συμμετοχή στο θέμα

Δημοσιευμένες Εικόνες

Έτσι είναι, από εκεί και πέρα δεν είπα ότι φταίει η C είπα απλά η διαχείριση switch/case δεν είναι "πρόβλημα" του Windows C API αλλά είναι ένα μοτίβο εκείνης της εποχής.

 

Επίσης δεν θεωρώ καν πρόβλημα το switch/case έτσι και αλλιώς.

 

Δεν καταλαβαίνω για ποιό λόγο εστιάζουμε στο switch εφόσον έτσι κι αλλιώς είναι trivial η αντικατάστασή του με κάποιο άλλο dispatch μηχανισμό, όπως π.χ. τελείως παραδειγματικά κάτι σαν

 

pfHandler = handlerMap[message_type];
pfHandler(...); 

 

Το βασικό πρόβλημα με όλα αυτά τα C API είναι πως δεν έχεις compile type safety. Από τη στιγμή που για να βάλεις ένα handler αναγκαστικά περνάς από π.χ. G_CALLBACK χάνεται οποιαδήποτε ελπίδα υπήρχε να σου πει ο compiler ότι κάνεις connect έναν handler του οποίου το signature είναι άλλα αντ' άλλων σε σχέση με το signal που πάει να κάνει handle (προφανώς το να πεις ότι όλοι οι handlers έχουν το ίδιο signature και να πρέπει μετά ο handler να βγάλει το φίδι από την τρύπα είναι τελείως κουραστικό και αντιπαραγωγικό και δε λύνει φυσικά το πρόβλημα γιατί πάλι βγάζοντας το φίδι δεν έχεις compile type safety).

 

Αντ' αυτού, με κάποιο strongly typed μηχανισμό ο οποίος βασίζεται σε σχετικά language features δεν έχεις ποτέ τέτοια προβλήματα. Κανένας C# compiler δε θα σου επιτρέψει να κάνεις compile αυτό:

 

button.Click += Environment.Exit;

 

Δεν έχω διάθεση να "διαφωνήσω" σχετικά με τα προφανή ωφέλη του να λειτουργούν έτσι τα πράγματα όταν γράφεις κώδικα. Το μόνο που θα πω επι τούτου είναι ότι σαν τελείως random παράδειγμα, έκανα google για "gtk+ bindings" και δεν απογοητεύτηκα: τα bindings του GTK+ σε C++ στα κύρια bullet points των πλεονεκτημάτων τους αναφέρουν ακριβώς αυτό σαν #2:

Type-safe signal handlers, in standard C++.

 

Δηλαδή, με άλλα λόγια, κάνοντάς το αυτό σε C χάνεις τη βοήθεια του compiler ο οποίος υπο άλλες συνθήκες θα μπορούσε να εντοπίσει ολόκληρη σειρά προβλημάτων πρωτού καν μπορέσεις να τρέξεις το πρόγραμμά σου. Και αυτό το μειονέκτημα αντισταθμίζεται από ποιά ακριβώς πλεονεκτήματα είπαμε;

 

Τυχόν παραληρήματα σχετικά με τα παραπάνω απλά θα αγνοηθούν. Σοβαρή κουβέντα (directx?) ευχαρίστως.

 

Ε ναι, για αυτό λέμε πως υπάρχουν πολύ ευκολότερα GUI frameworks από αυτά της C. Αν όμως για κάποιον λόγο πρέπει να χρησιμοποιήσεις C, μεταξύ Win32 και GTK+ το 2ο είναι μακράν πιο σύγχρονο, ενημερωμένο κι εύχρηστο.

 

Το GTK+ είναι όχι μόνο GUI framework αλλά και πολύ περισσότερα. To Win32 δεν είναι τίποτα απ' όλα αυτά. Και πραγματικά δεν καταλαβαίνω πως μπορεί να νομίζει κανείς ότι κάνει σοβαρή κουβέντα όταν έτσι στο χαλαρό συγκρίνει μήλα με πορτοκάλια.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δεν καταλαβαίνω για ποιό λόγο εστιάζουμε στο switch εφόσον έτσι κι αλλιώς είναι trivial η αντικατάστασή του με κάποιο άλλο dispatch μηχανισμό, όπως π.χ. τελείως παραδειγματικά κάτι σαν

[..]

Σωστά, απλά καθώς η κουβέντα πήγε στο switch / case και τα προβλήματα του Windows C API, θυμήθηκα πως αυτό το παράδειγμα διαχείρισης μηνυμάτων το συναντούσα αρκετά συχνά από παλιά οπότε επ' ευκαιρίας το υπενθύμισα.

 

Φυσικά σήμερα μπορούμε να το τροποποιήσουμε με την βοήθεια διαφόρων containers αλλά εκείνα τα χρόνια που δεν υπήρχαν έτοιμα διάφορα τέτοια καλούδια (συν την ελάχιστη μνήμη με την οποία έπρεπε να παλέψεις) η χρήση switch / case ήταν η πιο βατή (όχι απαραίτητα και η καλύτερη) λύση.

 

Με Callbacks πάνω σε messages λειτουργεί το framework του C++ Builder/Delphi (η VCL) και πράγματι τα βρίσκω αρκετά κομψά. Ο compiler εφαρμόζει type-safety και είτε θα διακόψει με σφάλμα ή τουλάχιστον θα παραπονεθεί με warning αν γίνει καμία στραβή. Βέβαια αυτό το κομμάτι του C++ Builder είναι ιδιοκατασκευή (γενικά σε αυτά τα θέματα παίζουν διάφορες ιδιοκατασκευές πχ. τα Signal / Slots της QT C++).

 

Το .NET πράγματι πάει πιο πέρα την υπόθεση και διευκολύνει πολύ, επίσης συμπαθητική λύση βρίσκω και τα Interface / Listener της Java (από την επαφή μου με Android programming).

 

Εκεί που δεν έχω εικόνα είναι στην Obective-C που χρησιμοποιεί η Apple και φημίζεται για την event/message-driven φύσης της (δυο φίλοι μου που δούλεψαν μαζί της για iPhone ..δεν θέλουν να την ξανά ακούσουν! :-P)

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Θα μπορούσες να μου εξηγήσεις defacer υπό ποια ιδιοφυή λογική η C και η C# είναι και τα 2 "μήλα" ενώ το Win32 API είναι "μήλο" και το GTK+ "πορτοκάλι"; Διότι μας χαρακτηρίζεις τη σύγκριση Win32 API με GTK+ ως "μήλα με πορτοκάλια" ενώ αμέσως πριν μας έχεις συγκρίνει C με C#.

 

Έπειτα, έχεις την εντύπωση πως οι developers του GTK+ επέλεξαν στην τύχη αυτή την προσέγγιση, επειδή ας πούμε δεν ήξεραν ότι μπορούν να παράσχουν απολύτως strongly typed μηχανισμό για τη σύνδεση των handlers, παρέχοντας για παράδειγμα διαφορετικές συναρτήσεις για κάθε υποστηριζόμενο event? (υπάρχουν κι άλλες λύσεις, π.χ με validated casting (που ήδη το κάνουν σε άλλες περιπτώσεις), αλλά ας το κρατήσουμε απλό... συν ότι έχει συζητηθεί ένα τέτοιο ενδεχόμενο για επόμενη έκδοση, χωρίς να έχει αποφασιστεί ακόμα).

 

Ρωτάω, γιατί μας αναρωτήθηκες με το γνωστό υφάκι σου: "Και αυτό το μειονέκτημα αντισταθμίζεται από ποιά ακριβώς πλεονεκτήματα είπαμε;"

 

Εφόσον λοιπόν δεν το γνωρίζεις, τα πλεονεκτήματα του non/loose type-safety έναντι του strong type-safety είναι πάντα τουλάχιστον δυο: μειωμένο overhead και αυξημένο flexibility. Και πάντα πρόκειται για trade-off, που κατά κανόνα σημαίνει πως όποιος στοιχειωδώς σοβαρός developer έχει επιλέξει την μια έναντι της άλλης λύσης έχει κάτσει κι έχει σταθμίσει τα υπερ και τα κατά πριν καταλήξει.

 

Το κατά πόσο λοιπόν είναι πιο εύκολο, πιο εύχρηστο, πιο ευέλικτο, πιο efficient ή/και πιο παραγωγικό το να χρησιμοποιείς ας πούμε functors μέσα από objects π.χ. κάθε φορά που θέλεις να συνδέσεις έναν handler με ένα event και να γράψεις τον handler με το gtkmm (τα c++bindings του GTK) συγκριτικά με το original C API επειδή για κάποιον δικό σου ιδιοφυή λόγο θεωρείς το strong type-safety το ιερό δισκοπότηρο του GUI programming, είναι κάτι που κατ' ελάχιστο ελέγχεται... για να μην πω τίποτα πιο βαρύ.

 

Βέβαια αυτά τα πράγματα προϋποθέτουν να έχει γράψει κανείς τουλάχιστον 3 γραμμές commercial κώδικα στη ζωή του για το θέμα στο οποίο υποτίθεται συμμετέχει αντί να ψάχνει bullets στο Google, οπότε κατανοώ την επαναλαμβανόμενη αδυναμία σου να κατανοήσεις την τεράστια διαφορά μεταξύ θεωρίας και πράξης. Αυτό που δεν κατανοώ βέβαια είναι η ανάγκη που νιώθεις να συμμετάσχεις δασκαλίστικα και μάλιστα με υφάκι και ειρωνίες σε νήματα που πραγματεύονται θέματα για τα οποία δεν έχεις την παραμικρή εμπειρία για να μην πω επαφή. Αλλά οκ, that's life.

 

@AlbNik:

 

Επειδή η επαφή μου με GUI programming μέσω .net τείνει στο 0, πως το κάνεις σε .net αυτό με το close button χωρίς να αντιστοιχήσεις handler?

 

Επίσης, θυμάσαι κάποια από τις περιπτώσεις που χρειάστηκε να καταφύγεις σε απευθείας "συνεννόηση" με το Win32 API; Υποθέτω εξάντλησες τα .net εργαλεία που είχες στη διάθεσή σου όταν χρειάστηκες μεγαλύτερη ευελιξία, ναι;

 

Ότι και να ήταν, πιστεύω είναι χρήσιμο να υπάρχει στο νήμα για όσους το παρακολουθούμε.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Θα μπορούσες να μου εξηγήσεις defacer υπό ποια ιδιοφυή λογική η C και η C# είναι και τα 2 "μήλα"

 

Εεε... είναι και οι 2 γλώσσες προγραμματισμού; Ανάμεσα στις οποίες καλούμαστε να επιλέξουμε γενικότερα αλλά και ειδικότερα στα πλαίσια του συγκεκριμένου topic ("μη το κάνεις με C, κάντο με κάτι άλλο")?

 

Έχεις καμία άλλη απορία επιπέδου δημοτικού;

 

Έπειτα, έχεις την εντύπωση πως οι developers του GTK+ επέλεξαν στην τύχη αυτή την προσέγγιση, επειδή ας πούμε δεν ήξεραν ότι μπορούν να παράσχουν απολύτως strongly typed μηχανισμό για τη σύνδεση των handlers, παρέχοντας για παράδειγμα διαφορετικές συναρτήσεις για κάθε υποστηριζόμενο event? (υπάρχουν κι άλλες λύσεις, π.χ με validated casting (που ήδη το κάνουν σε άλλες περιπτώσεις), αλλά ας το κρατήσουμε απλό... συν ότι έχει συζητηθεί ένα τέτοιο ενδεχόμενο για επόμενη έκδοση, χωρίς να έχει αποφασιστεί ακόμα).

 

Ρωτάω, γιατί μας αναρωτήθηκες με το γνωστό υφάκι σου: "Και αυτό το μειονέκτημα αντισταθμίζεται από ποιά ακριβώς πλεονεκτήματα είπαμε;"

 

Και με τη γνωστή τακτική σου βέβαια με αφήνεις χωρίς σοβαρή απάντηση. Αντί να κρύβεσαι πίσω από τα φουστάνια των οποιωνδήποτε τρίτων developers (οι οποίοι "αφού το επέλεξαν αυτό είναι το σωστό"), θα μπορούσες (μόνο θεωρητικά βέβαια) να επιχειρηματολογήσεις μόνος σου.

 

 

 

Black boxes... :lol: :lol: :lol:

 

 

 

Από αυτές τις ιστορίες που λες για διαφορετικές συναρτήσεις που αποτελούν strongly typed μηχανισμό συνειδητοποιώ ότι με τα χρόνια μάλλον το χάνουμε σιγά σιγά, ή ίσως ποτέ δεν έμαθες κάποια πράγματα για τη C όπως το παρακάτω:

 

6.3.2.3/8:

A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer. If a converted pointer is used to call a function whose type is not compatible with the pointed-to type, the behavior is undefined.

 

Επομένως δεν υπάρχει τίποτα που να μπορεί να σ' εμποδίσει να κάνεις αυτό:

void foo(int x, char y) {}
void bar(char* x, struct whatever y) {}
typedef void (*fooPtr)(int, char);

fooPtr fp = bar; // !!!!!!!! 

και κατ' επέκταση να περάσεις λάθος συνάρτηση ως callback σε οτιδήποτε, το οποίο callback όταν κληθεί θα έχουμε UB με όλα τα γνωστά ωραία που αυτό συνεπάγεται.

 

Αν διαφωνείς μαζί μου, βρες τα με τον compiler σου πρώτα.

 

Εφόσον λοιπόν δεν το γνωρίζεις, τα πλεονεκτήματα του non/loose type-safety έναντι του strong type-safety είναι πάντα τουλάχιστον δυο: μειωμένο overhead και αυξημένο flexibility. Και πάντα πρόκειται για trade-off, που κατά κανόνα σημαίνει πως όποιος στοιχειωδώς σοβαρός developer έχει επιλέξει την μια έναντι της άλλης λύσης έχει κάτσει κι έχει σταθμίσει τα υπερ και τα κατά πριν καταλήξει.

 

Παίρνεις ναρκωτικά? Πώς θα μπορούσε σε οποιοδήποτε σύμπαν μια γενικής χρήσης g_signal_connect() να έχει μειωμένο overhead σε σχέση με μια π.χ. σύμφωνα με την παραπάνω προτασή σου ειδική g_specific_signal_connect()? (ασχέτως του ότι επειδή C όπως λέω παραπάνω η ειδική δε θα παρέχει type safety άρα τζάμπα κόπος και κούραση).

 

Όσο για το αυξημένο flexibility μάλλον στην προκειμένη θα εννοείς flexibility στο με πόσους τρόπους μπορείς να γράψεις bugs. Εγώ λέω να γράφουμε σε assembly, εκεί να δεις flexibility. Η μεταβλητή λέει είναι εκτός scope και βλακείες.

 

 

Το κατά πόσο λοιπόν είναι πιο εύκολο, πιο εύχρηστο, πιο ευέλικτο, πιο efficient ή/και πιο παραγωγικό το να χρησιμοποιείς ας πούμε functors μέσα από objects π.χ. κάθε φορά που θέλεις να συνδέσεις έναν handler με ένα event και να γράψεις τον handler με το gtkmm (τα c++bindings του GTK) συγκριτικά με το original C API επειδή για κάποιον δικό σου ιδιοφυή λόγο θεωρείς το strong type-safety το ιερό δισκοπότηρο του GUI programming, είναι κάτι που κατ' ελάχιστο ελέγχεται... για να μην πω τίποτα πιο βαρύ.

 

Βέβαια αυτά τα πράγματα προϋποθέτουν να έχει γράψει κανείς τουλάχιστον 3 γραμμές commercial κώδικα στη ζωή του για το θέμα στο οποίο υποτίθεται συμμετέχει αντί να ψάχνει bullets στο Google, οπότε κατανοώ την επαναλαμβανόμενη αδυναμία σου να κατανοήσεις την τεράστια διαφορά μεταξύ θεωρίας και πράξης. Αυτό που δεν κατανοώ βέβαια είναι η ανάγκη που νιώθεις να συμμετάσχεις δασκαλίστικα και μάλιστα με υφάκι και ειρωνίες σε νήματα που πραγματεύονται θέματα για τα οποία δεν έχεις την παραμικρή εμπειρία για να μην πω επαφή. Αλλά οκ, that's life.

 

Παραληρήματα.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δεν ξεκινάς σιγά-σιγά να ψάχνεις στο google μπας και βρεις κάνα bullet για κάνα compiler που δεν βγάζει warning στο παρακάτω...

 

 

#include <stdio.h>
#include <stdlib.h>

int f1( char *str )
{
    printf( "%s\n", str );
    return 1;
}

void f2( int x )
{
    printf( "%d\n", x );
}

void foo( int (*cb)(char *), char *str )
{
    (*cb)( str );
}

int main( void )
{
    foo( &f2, "hello" );

    system( "pause" );
}
 

 

Άμα καταλάβεις και το γιατί, κερδίζεις ρούμπο.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δεν προλαβαίνω να αφομοιώνω γνώση σήμερα. Μόλις έμαθα ότι τα warnings για κάτι που επιτρέπεται από τη γλώσσα μπορούμε να τα βαφτίσουμε type safety.

 

Αναρωτιέμαι πρώτον, αυτοί οι ανίδεοι που έγραψαν τον compiler δεν ξέρουν ότι μ' αυτό τον τρόπο έχεις μεγαλύτερο flexibility; Γιατί θέλουν να μας περιορίσουν; Και πως τολμούν να υποννοούν ότι υπάρχει οποιοδήποτε θέμα που η C δεν το χειρίζεται με τον καλύτερο τρόπο στο σύμπαν;

 

Και δεύτερον, μήπως να δοκίμαζες και καμία γλώσσα που όντως έχει type safety για να καταλάβεις τη διαφορά στην πράξη;

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δεν προλαβαίνω να αφομοιώνω γνώση σήμερα. Μόλις έμαθα ότι τα warnings για κάτι που επιτρέπεται από τη γλώσσα μπορούμε να τα βαφτίσουμε type safety.

 

Για να πούμε του στραβού το δίκιο, έχει ένα point εδώ ο... θεωρητικός. Εμείς του δημοτικού στην πράξη κάνουμε πάντα compile με -Werror και παρασύρθηκα.

 

Η ουσία παραμένει αναλλοίωτη όμως, μιας και η παρακάτω επιχειρηματάρα ...

 

Επομένως δεν υπάρχει τίποτα που να μπορεί να σ' εμποδίσει να κάνεις αυτό:

void foo(int x, char y) {}
void bar(char* x, struct whatever y) {}
typedef void (*fooPtr)(int, char);

fooPtr fp = bar; // !!!!!!!! 
και κατ' επέκταση να περάσεις λάθος συνάρτηση ως callback σε οτιδήποτε, το οποίο callback όταν κληθεί θα έχουμε UB με όλα τα γνωστά ωραία που αυτό συνεπάγεται.

 

καταρρίπτεται μεγαλοπρεπώς έτσι κι αλλιώς. Ή μάλλον όχι, όντως υπάρχει κάτι που δεν σε εμποδίζει να περνάς ότι γουστάρεις ως callback στην επιχειρηματάρα: το να έχεις τελείως κλειστά τα warnings... αυτό δηλαδή που κάνουμε όλοι όταν γράφουμε κώδικα, αλλά κυρίως όσοι έχουμε γράψει έστω και 1 γραμμή κώδικα για να την πουλήσουμε και να ζήσουμε.

 

Αναρωτιέμαι πρώτον, αυτοί οι ανίδεοι που έγραψαν τον compiler δεν ξέρουν ότι μ' αυτό τον τρόπο έχεις μεγαλύτερο flexibility; Γιατί θέλουν να μας περιορίσουν; Και πως τολμούν να υποννοούν ότι υπάρχει οποιοδήποτε θέμα που η C δεν το χειρίζεται με τον καλύτερο τρόπο στο σύμπαν;

 

Και δεύτερον, μήπως να δοκίμαζες και καμία γλώσσα που όντως έχει type safety για να καταλάβεις τη διαφορά στην πράξη;

 

Full of nothing!

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

@AlbNik:

 

Επειδή η επαφή μου με GUI programming μέσω .net τείνει στο 0, πως το κάνεις σε .net αυτό με το close button χωρίς να αντιστοιχήσεις handler?

 

Επίσης, θυμάσαι κάποια από τις περιπτώσεις που χρειάστηκε να καταφύγεις σε απευθείας "συνεννόηση" με το Win32 API; Υποθέτω εξάντλησες τα .net εργαλεία που είχες στη διάθεσή σου όταν χρειάστηκες μεγαλύτερη ευελιξία, ναι;

 

Ότι και να ήταν, πιστεύω είναι χρήσιμο να υπάρχει στο νήμα για όσους το παρακολουθούμε.

 

Με την ShowDialog() εμφανίζεις τη φόρμα. Το x κλείνει τη φόρμα χωρίς να γράψεις κάτι, μπορείς να το κάνεις να ΜΗΝ την κλείσει  αν χειριστείς το FormClosing  event  (FormClosingEventArgs  e.Cancel = true) . 

Γενικά μπορείς να ορίσεις πολλά properties χωρίς να γράψεις κώδικα. Να κλείνει με Enter η Esc (Ok Cancel) , να είναι TopMost, χρώματα, transparency... (δες το properties dialog στο Visual Studio) .

 

To winapi το χρειάστηκα λίγες φορές,

π.χ. θέλω να χρησιμοποιώ το TabControl για wizard η multipanel, δηλαδη να εμφανιζω προγραμματιστικά καποιο tabpage του αλλά να κρύψω τα tabheaders για να μην μπορεί ο χρήστης.  Με αυτό των κώδικα κάνεις inherit το δικό σου tabcontrol χωρίς headers.

class TablessControl : TabControl {
  protected override void WndProc(ref Message m) {
    // Hide tabs by trapping the TCM_ADJUSTRECT message
    if (m.Msg == 0x1328 && !DesignMode) m.Result = (IntPtr)1;
    else base.WndProc(ref m);
  }
}

 

 

Στο listview έχουν παραμελήσει να εμφανίσουν τα up/down arrows όταν κάνεις ταξινόμηση κατά κάποια στήλη 

http://stackoverflow.com/questions/254129/how-to-i-display-a-sort-arrow-in-the-header-of-a-list-view-column-using-c/254139#254139

 

η να κάνεις collapse/expand τα grouped items. 

http://www.codeproject.com/Articles/31276/Add-Group-Collapse-Behavior-on-a-Listview-Control

 

Ήθελα η forma να κάνει flashing όπως το live messenger , εδώ χρειάστηκε p/invoke  η FlashWindow.

 

Πρόγραμμα που παρακολουθεί τα copy-paste του χρήστη 

http://stackoverflow.com/questions/621577/clipboard-event-c-sharp

 

Εννοείται πρώτα κοιτάζω μήπως το έχει το ΝΕΤ (δλδ έκανε τα p/invoke και τα winapi κάποιος υπάλληλος της microsoft).

Γενικά στο ΝΕΤ και σε κάθε πετυχημένο framework (πρέπει) τα απλά πράγματα γίνονται εύκολα και τα πιο περίπλοκα εφικτά.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Με την ShowDialog() εμφανίζεις τη φόρμα. Το x κλείνει τη φόρμα χωρίς να γράψεις κάτι, μπορείς να το κάνεις να ΜΗΝ την κλείσει  αν χειριστείς το FormClosing  event  (FormClosingEventArgs  e.Cancel = true) . 

Γενικά μπορείς να ορίσεις πολλά properties χωρίς να γράψεις κώδικα. Να κλείνει με Enter η Esc (Ok Cancel) , να είναι TopMost, χρώματα, transparency... (δες το properties dialog στο Visual Studio) .

 

Αυτό σε GTK+ μου θυμίζει πολύ την: gtk_dialog_run() και νομίζω υπάρχει κάτι αντίστοιχο και σε Win32 API, αλλά για αυτό το τελευταίο δεν είμαι και πολύ σίγουρος.

 

 

To winapi το χρειάστηκα λίγες φορές,

π.χ. θέλω να χρησιμοποιώ το TabControl για wizard η multipanel, δηλαδη να εμφανιζω προγραμματιστικά καποιο tabpage του αλλά να κρύψω τα tabheaders για να μην μπορεί ο χρήστης.  Με αυτό των κώδικα κάνεις inherit το δικό σου tabcontrol χωρίς headers.

class TablessControl : TabControl {
  protected override void WndProc(ref Message m) {
    // Hide tabs by trapping the TCM_ADJUSTRECT message
    if (m.Msg == 0x1328 && !DesignMode) m.Result = (IntPtr)1;
    else base.WndProc(ref m);
  }
}
 

 

Στο listview έχουν παραμελήσει να εμφανίσουν τα up/down arrows όταν κάνεις ταξινόμηση κατά κάποια στήλη 

http://stackoverflow.com/questions/254129/how-to-i-display-a-sort-arrow-in-the-header-of-a-list-view-column-using-c/254139#254139

 

η να κάνεις collapse/expand τα grouped items. 

http://www.codeproject.com/Articles/31276/Add-Group-Collapse-Behavior-on-a-Listview-Control

 

Ήθελα η forma να κάνει flashing όπως το live messenger , εδώ χρειάστηκε p/invoke  η FlashWindow.

 

Πρόγραμμα που παρακολουθεί τα copy-paste του χρήστη 

http://stackoverflow.com/questions/621577/clipboard-event-c-sharp

 

Thanks για τα links, θα τα κοιτάξω με καθαρό μυαλό κάποια άλλη στιγμή, κι αν χρειαστώ τίποτα διευκρινήσεις θα επανέλθω με ερωτήσεις :)

 

Εννοείται πρώτα κοιτάζω μήπως το έχει το ΝΕΤ (δλδ έκανε τα p/invoke και τα winapi κάποιος υπάλληλος της microsoft).

Γενικά στο ΝΕΤ και σε κάθε πετυχημένο framework (πρέπει) τα απλά πράγματα γίνονται εύκολα και τα πιο περίπλοκα εφικτά.

 

Συμφωνώ! Με την προϋπόθεση όμως πως σου δίνει το framework και την δυνατότητα να πας και πιο low level αν και όταν χρειαστεί.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Για να πούμε του στραβού το δίκιο, έχει ένα point εδώ ο... θεωρητικός. Εμείς του δημοτικού στην πράξη κάνουμε πάντα compile με -Werror και παρασύρθηκα.

 

Η ουσία παραμένει αναλλοίωτη όμως, μιας και η παρακάτω επιχειρηματάρα ...

 

καταρρίπτεται μεγαλοπρεπώς έτσι κι αλλιώς. Ή μάλλον όχι, όντως υπάρχει κάτι που δεν σε εμποδίζει να περνάς ότι γουστάρεις ως callback στην επιχειρηματάρα: το να έχεις τελείως κλειστά τα warnings... αυτό δηλαδή που κάνουμε όλοι όταν γράφουμε κώδικα, αλλά κυρίως όσοι έχουμε γράψει έστω και 1 γραμμή κώδικα για να την πουλήσουμε και να ζήσουμε.

 

 

Full of nothing!

Χωρίς να θέλω να ρίξω λάδι στη φωτιά και εγώ πιστεύω πως δεν συγκρίνονται οι δύο έννοιες. Ναι μεν συμφωνώ μαζί σου ότι ο compiler παράγει warning (το συγκεκριμένο μάλιστα έχω την εντύπωση ότι δεν χρειάζεται καν -Wall) οπότε θα δεις αμέσως ότι κάτι παίζει αλλά δεν συγκρίνεται με το να έχεις type-safety.

 

Επίσης το να χρησιμοποιείς -Werror δεν είναι πανάκεια και μάλιστα θεωρείται κακή πρακτική από τους developers του gcc με το επιχείρημα ότι στατιστικά κάθε έκδοση του compiler γίνεται και πιο αυστηρή και προστίθενται νέες warning. Έτσι μπορεί ένας κώδικας που έχοντας ενεργοποιημένο το -Werror γινόταν compile τζάμι με την έκδοση Χ να μην γίνεται compile με την Χ+1 λόγω ότι υπάρχει ένα νέο warning που μετατράπηκε σε error λόγω της παραπάνω παραμέτρου.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημοσ. (επεξεργασμένο)

Αυτό σε GTK+ μου θυμίζει πολύ την: gtk_dialog_run() και νομίζω υπάρχει κάτι αντίστοιχο και σε Win32 API, αλλά για αυτό το τελευταίο δεν είμαι και πολύ σίγουρος.

Χμ.. δυστυχώς δεν γνωρίζω από GTK(+) αλλά σε Windows API έχουμε το concept των dialogs, τα οποία (με κάποιους περιορισμούς βέβαια) μπορούν να διευκολύνουν ως έναν βαθμό την διαχείριση του UI (γλυτώνεις χρόνο στο στήσιμο και την προετοιμασία του παραθύρου, φορτώνονται αυτόματα τα controls, έχουν μερικές πιο συνοπτικές συναρτήσεις και μένει μόνο να γραφθεί το Dialog Procedure (switch/case) δηλαδή).

 

 

Ακολουθεί ένα μικρό πρόγραμμα που δημιουργεί ένα διάλογο αλλά με ανορθόδοξο τρόπο, επειδή δεν μπορώ να συμπεριλάβω το Dialog Template RC εδώ, το κατασκευάζω on the fly (πολύ κακιά πρακτική btw) για αυτό ο κώδικας βγαίνει (και είναι) βρώμικος - σκέψου ότι υπό φυσιολογικές συνθήκες πάμε κατευθείαν στο DialogBoxIndirect το οποίο και θα ήταν ένα μια κλήση στην συνάρτηση DialogBox μαζί με ένα Dialog Template Resource που μας παρέχει "έτοιμο" ο (Resource) Compiler μας και το οποίο ως επί το πλείστο σχεδιάζουμε οπτικά (με κάποιον Dialog Editor) στο IDE μας ή παλαιότερα με κάποιο εξωτερικό πρόγραμμα (πχ. Borland Resource Workshop :-D)..

/*
 * Dialog on the fly v2, xdir.
 * 	tested under C++ Builder!
 */
#include <windows.h>

BOOL CALLBACK dlgProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
	/*
	 * Dialog Template, under normal circumstances it will be automatically generated
	 * by the Resource Compiler (of your IDE etc) and the user WILL NEVER have to
	 * do this manually but via DialogBox & MAKEINTRESOURCE 
	 */
	struct Template
	{
		DLGTEMPLATE dlgTemplate;
		WORD wDummy[2];
		wchar_t Caption[9];
	}Template = { 0 };

	Template.dlgTemplate.style = WS_CAPTION|WS_SYSMENU|DS_CENTER;
	Template.dlgTemplate.cx = 150;
	Template.dlgTemplate.cy = 50;
	lstrcpyW(Template.Caption, L"Dialog!");

	/* Show dialog! */
	const int nErr = DialogBoxIndirect(hInstance, (LPCDLGTEMPLATE)&Template,
		NULL, dlgProc);

	/* Success? */
	if(nErr <= 0)
		MessageBox(NULL, "DialogBoxIndirect error!", NULL, MB_ICONSTOP);

	return 0;
}

/* Dialog Procedure! */
BOOL CALLBACK dlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	static HDC hDC;
	static PAINTSTRUCT PS;
	static RECT rcDlg;

	switch(msg)
	{
		case WM_INITDIALOG:
			GetClientRect(hDlg, &rcDlg);
			return 1;
		case WM_PAINT:
			hDC = BeginPaint(hDlg, &PS);
			FillRect(hDC, &rcDlg, (HBRUSH)GetStockObject(LTGRAY_BRUSH));
			SetBkMode(hDC, TRANSPARENT);
			DrawText(hDC, "Hello world!", -1, &rcDlg, DT_CENTER|DT_SINGLELINE|DT_VCENTER);
			EndPaint(hDlg, &PS);
			return 1;
		case WM_ERASEBKGND:
			InvalidateRect(hDlg, NULL, FALSE);
			return 1;
		case WM_COMMAND:
			switch(wParam)
			{
				case WM_DESTROY:
					EndDialog(hDlg, 1);
					return 1;
			}
			return 0;
	}

	return 0;
}

post-41640-0-66993000-1366228833_thumb.png

Υ.Γ.

Στην έκδοση 2 τροποποίησα τον κώδικα ώστε να είναι πιο καθαρός.

 

 

Επεξ/σία από Directx
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Χμ.. δυστυχώς δεν γνωρίζω από GTK(+) αλλά σε Windows API έχουμε το concept των dialogs, τα οποία (με κάποιους περιορισμούς βέβαια) μπορούν να διευκολύνουν ως έναν βαθμό την διαχείριση του UI (γλυτώνεις χρόνο στο στήσιμο και την προετοιμασία του παραθύρου, φορτώνονται αυτόματα τα controls, έχουν μερικές πιο συνοπτικές συναρτήσεις και μένει μόνο να γραφθεί το Dialog Procedure (switch/case) δηλαδή).

 

 

Ακολουθεί ένα μικρό πρόγραμμα που δημιουργεί ένα διάλογο αλλά με ανορθόδοξο τρόπο, επειδή δεν μπορώ να συμπεριλάβω το Dialog Template RC εδώ, το κατασκευάζω on the fly (πολύ κακιά πρακτική btw) για αυτό ο κώδικας βγαίνει (και είναι) βρώμικος - σκέψου ότι υπό φυσιολογικές συνθήκες πάμε κατευθείαν στο DialogBoxIndirect το οποίο και θα ήταν ένα μια κλήση στην συνάρτηση DialogBox μαζί με ένα Dialog Template Resource (το οποίο τώρα κατασκευάζω με κώδικα & φορτώνω χειροκίνητα σε ένα Global Memory Object κλπ) που μας παρέχει "έτοιμο" ο (Resource) Compiler μας και το οποίο ως επί το πλείστο σχεδιάζουμε οπτικά (με κάποιον Dialog Editor) στο IDE μας ή παλαιότερα με κάποιο εξωτερικό πρόγραμμα (πχ. Borland Resource Workshop :-D)..

/*
 * Dialog on the fly, xdir.
 * 	tested under C++ Builder!
 */
#include <windows.h>

#define _DIALOG_CAPTION L"Dialog!\0"

#define _MSGBOX(err)	MessageBox(NULL, err, NULL, MB_ICONSTOP)

BOOL CALLBACK dlgProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
	/*
	 * Dialog Template, under normal circumstances it will be automatically generated
	 * by the Resource Compiler (of your IDE etc) and the user WILL NEVER have to
	 * do this manually but via DialogBox & MAKEINTRESOURCE 
	 */
	const DLGTEMPLATE dlgTemplate = {
		WS_CAPTION|WS_SYSMENU, 0, 0, 0, 0, 150, 50
	};

	/* Load Dialog Template into memory, as described in WinAPI documentation .. */
	const DWORD dwTemplateLen = sizeof(DLGTEMPLATE) + (sizeof(WORD) * 3) + sizeof(_DIALOG_CAPTION);
	HGLOBAL hTemplate = NULL;
	BYTE *ptrTemplate = NULL;

	if(!(hTemplate = GlobalAlloc(GHND, dwTemplateLen)))
	{
		_MSGBOX("GlobalAlloc error!");
		return 1;
	}	
	if(!(ptrTemplate = (LPBYTE)GlobalLock(hTemplate)))
	{
		GlobalFree(hTemplate);
		_MSGBOX("GlobalLock error!");
		return 1;
	}

	CopyMemory(ptrTemplate, &dlgTemplate, sizeof(DLGTEMPLATE));		
	CopyMemory(&ptrTemplate[sizeof(DLGTEMPLATE) + (sizeof(WORD) * 2)], _DIALOG_CAPTION,
		sizeof(_DIALOG_CAPTION));
	
	/* Show dialog! */
	const int nErr = DialogBoxIndirect(hInstance, (LPCDLGTEMPLATE)ptrTemplate,
		NULL, dlgProc);

	/* Success? */
	if(nErr <= 0)
		MessageBox(NULL, "DialogBoxIndirect error!", NULL, MB_ICONSTOP);

	/* Bye.. */
	GlobalUnlock(ptrTemplate);	
	GlobalFree(hTemplate);

	return 0;
}

/* Dialog Procedure! */
BOOL CALLBACK dlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	static HDC hDC;
	static PAINTSTRUCT PS;
	static RECT rcDlg;

	switch(msg)
	{
		case WM_INITDIALOG:			
			GetClientRect(hDlg, &rcDlg);
			return 1;
		case WM_PAINT:
			hDC = BeginPaint(hDlg, &PS);
			FillRect(hDC, &rcDlg, (HBRUSH)GetStockObject(LTGRAY_BRUSH));
			SetBkMode(hDC, TRANSPARENT);
			DrawText(hDC, "Hello world!", -1, &rcDlg, DT_CENTER|DT_SINGLELINE|DT_VCENTER);
			EndPaint(hDlg, &PS);
			return 1;
		case WM_ERASEBKGND:
			InvalidateRect(hDlg, NULL, FALSE);
			return 1;
		case WM_COMMAND:
			switch(wParam)
			{
				case WM_DESTROY:
					EndDialog(hDlg, 1);
					return 1;
			}
			return 0;
	}

	return 0;
}

attachicon.gifdialog.png

 

 

 

Ναι, από ότι έχω συναντήσει όλα τα GUI έχουν το concept του dialog, και συνήθως (αλλά όχι απαραίτητα) αναφέρονται σε modal παράθυρα με περιορισμένη λειτουργικότητα αλλά αυτοματοποιημένη για συνηθισμένα tasks.

 

Κάτι αντίστοιχο με τον κώδικα που παρέθεσες φίλε Dx, σε GTK+ θα μπορούσε να γραφτεί κάπως έτσι...

 

 

#include <gtk/gtk.h>
#include <stdio.h>	/* for debugging purposes */

#define MANUALLY	0
#define DLG_TITLE	"On the Fly Dialog"

/* --------------------------------------------------- */
int main( int argc, char **argv )
{
	GtkWidget *dialog = NULL, *box = NULL, *label = NULL;
	gint response;

	gtk_init( &argc, &argv );

#if MANUALLY
	/* create dialog */
	dialog = gtk_dialog_new();

	/* set it modal woith no parent (transient) window */
	gtk_window_set_modal( GTK_WINDOW( dialog ), TRUE );
	gtk_window_set_transient_for(
		GTK_WINDOW( dialog ),
		GTK_WINDOW( NULL )
		);

	/* set title */
	gtk_window_set_title( GTK_WINDOW( dialog ), DLG_TITLE );

	/* add buttons. */
	gtk_dialog_add_button( GTK_DIALOG( dialog ), "1", 1 );
	gtk_dialog_add_button( GTK_DIALOG( dialog ), "2", 2 );
	gtk_dialog_add_button( GTK_DIALOG( dialog ), "3", 3 );

#else

	/* or using a provided convenient function */
	dialog = gtk_dialog_new_with_buttons(
			DLG_TITLE,
			GTK_WINDOW( NULL ),
			GTK_DIALOG_MODAL,
			"1", 1,
			"2", 2,
			"3", 3,
			NULL
			);
#endif

	/* create label */
	label = gtk_label_new( "Hello world" );

	/* for version < 2.14 replace below line with: box = GTK_DIALOG( dialog )->vbox; */
	box = gtk_dialog_get_content_area( GTK_DIALOG( dialog ) );

	gtk_box_pack_start( GTK_BOX( box ), label, TRUE, TRUE, 0 );

	/* show dialog */
	gtk_widget_show_all( dialog );

	/* run dialog */
	response = gtk_dialog_run( GTK_DIALOG(dialog) );

	/* handle selection */
	printf( "You selected: %d\n", response );

	/* destroy dialog */
	gtk_widget_destroy(dialog);

	return 0;
}
post-38307-0-83344900-1366259245_thumb.jpg

 

 

Το δείχνω και με χειροκίνητο χτίσιμο (MANUALLY) και με χρήση της convenient function gtk_dialog_new_with_buttons(). Το συγκεκριμένο θα μπορούσε να γίνει και με την convenient function gtk_message_dialog_new(), που είναι το κοντινότερο αντίστοιχο της MessageBox() στο Win32 API.

 

Ίσως παρατήρησες πως σε αντίθεση με τον κώδικα που παρέθεσες από το Win32 API, δεν υπάρχουν callback functions attached σε signals/events του dialog, κι απλώς διαβάζω την τιμή επιστροφής της gtk_dialog_run(). Αυτό βγάζει μικρότερο κώδικα συγκριτικά με το δικό σου παράδειγμα από το Win32 API, αλλά λειτουργεί εις βάρος της ευελιξίας για διαχείριση μη αυτοματοποιημένων events.

 

Bασικά μπορούν κι αυτά να διαχειριστούν μέσω των υπόλοιπων συναρτήσεων του GtkDialog interface, ας πούμε μέσω των gtk_dialog_get_action_area() και gtk_dialog_get_content_area() ή/και με την gtk_dialog_repsonse() αλλά έτσι αρχίζει να γίνεται πολύ messy το πράγμα, οπότε σε αυτές τις περιπτώσεις συνήθως εξυπηρετεί καλύτερα να διαχειριστούμε εξαρχής το dialog ως window με callbacks, g_signal_connect(), κλπ. Πιθανόν να υπάρχει και ενδιάμεση λύση και να μην τη γνωρίζω.

 

@imitheos:

 

Σε γενικό κι αόριστο context σαφώς και δεν συγκρίνονται οι δυο έννοιες (έσπευσα άλλωστε να το πω κι εγώ). Στο context όμως του συγκεκριμένου νήματος και πιο συγκεκριμένα στην κόντρα με τον defacer του καταρρίπτει με μια γραμμή όλη του την "επιχειρηματολογία" περί "δεν σε εμποδίζει κανείς να κάνεις αυτό και τούτο και το άλλο".

 

Αν θεωρείς πως η ουσία του νήματος είναι το αν έγραψα εκ περιδρομής ή όχι τις λέξεις "απολύτως strongly" και δεν γνωρίζω τι είναι το strong και τι το weak type, it's fine by me.

 

Εγώ πάντως θεωρώ πιο σημαντικό πως ο defacer για μια ακόμα φορά επινοεί δικές του θεωρίες για να συμμετάσχει αφ' υψηλού σε νήμα που πραγματεύεται θέμα με το οποίο είναι ηλίου φαεινότερο πως δεν έχει την παραμικρή εμπειρία (κατά τη άποψή μου ούτε καν επαφή)... ελπίζω πως it's fine by you.

Ούτε καν compile δεν έκανε τον κώδικα που μας παράθεσε ως βασικό του επιχείρημα, μιλάμε για τέτοια σιγουριά ο άνθρωπος (ή αν τον έκανε, λέμε τώρα καμιά μπιπ να περνάει η ώρα, είχε κλειστά τα warnings... μάλλον από συνήθεια υποθέτω).

 

Σε ότι αφορά το -Werror, εγώ ξέρω πως όπου κι αν έχω δουλέψει το -Werror (και όποιο αντίστοιχο άλλων compilers) είναι υποχρεωτικό μέχρι αποδείξεως πως είναι περιττό (μια φορά που δεν ήταν, το επέβαλλα εγώ :P)

 

Δηλαδή, αν για παράδειγμα σου βγάζει ως error ένα warning που ξέρεις πως δεν πειράζει το κάνεις exclude μονάχα αυτό, είτε με command line flag, είτε με diagnostic #pragma, είτε με οποιονδήποτε άλλο τρόπο σου δίνει ο compiler (αυτούς τους 2 τρόπους θυμάμαι αυτή τη στιγμή). Σε κάποιες περιπτώσεις το κλείναμε τελείως (όταν π.χ. ο compiler κατηγοριοποιούσε μαζί warnings που το ένα το θέλαμε να το βγάζει ενώ το άλλο όχι). Προφανώς όμως τα warnings ήταν πάντα ανοιχτά no matter what.

 

Από εκεί και πέρα τι άλλο να σου πω, μάλλον στάθηκα άτυχος και όπου δουλεύω εφαρμόζουν κακές πρακτικές.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Το συγκεκριμένο θα μπορούσε να γίνει και με την convenient function gtk_message_dialog_new(), που είναι το κοντινότερο αντίστοιχο της MessageBox() στο Win32 API.

Yup! Το MessageBox σε αυτή την περίπτωση είναι ότι πιο κοντινό προς τον κώδικα του GTK+ (αλλά καθώς δεν ασχολούμαι υπέθεσα ότι μιλάμε γενικά για Dialogs και όχι ειδικά για "Alert" ή Message Box), αν μάλιστα θέλεις να τροποποιήσεις και κάποιες από τις πιο προχωρημένες παραμέτρους του πας στην MessageBoxIndirect, αν τώρα χρειάζεται κάτι παραπάνω τότε αναγκαστικά πρέπει να γράψεις ένα δικό σου Dialog.

 

Για την ιστορία εδώ είχα αναρτήσει την υλοποίηση ενός Grid Form σε C++ Builder VCL, ίσως φανεί ενδιαφέρον μιας και η κουβέντα οδεύει προς τα RAD frameworks σιγά, σιγά.

 

 

 

Υ.Γ.

Από τα πιο κουραστικά framework σε σχέση με την διαχείριση διαλόγων είναι το Android πάντως, βλέπεις οι διάλογοι του δεν είναι modal οπότε δεν μπορείς να γράψεις τον συνηθισμένο κώδικα:

 /* Wait for user choice.. */
 int UserChoice = fooAlert("Continue?");
αλλά καταλήγεις σε ένα ασύγχρονο Listener :-/

 

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

 

Με την ShowDialog() εμφανίζεις τη φόρμα. Το x κλείνει τη φόρμα χωρίς να γράψεις κάτι, μπορείς να το κάνεις να ΜΗΝ την κλείσει  αν χειριστείς το FormClosing  event  (FormClosingEventArgs  e.Cancel = true) . 

Γενικά μπορείς να ορίσεις πολλά properties χωρίς να γράψεις κώδικα. Να κλείνει με Enter η Esc (Ok Cancel) , να είναι TopMost, χρώματα, transparency... (δες το properties dialog στο Visual Studio) .

 

Στην ουσία δεν είναι ότι δεν γράφεται κώδικας. Απλά δεν τον γράφεις εσύ, το κάνει το IDE για εσένα. Εκτός από το X που είναι στη αντικείμενο της Form εξορισμού. Αν ανοίξεις το δεύτερο .cs (αυτό με το Generated Code) της φόρμας θα δεις ότι κάθε επιλογή σου από τα properties πάει και την γράφει εκεί (όπως και event κτλ). Αν δεν είχες το VS θα έπρεπε να τα γράφεις μόνος σου.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα

  • Δημιουργία νέου...