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

C++ & ClipBoard


Dvs

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

Δημοσ.

Einai grammenos se Borland Builder

 

>

AnsiString pText = Edit1->Text;

 // Open Clipboard
 if ( !OpenClipboard(this->Handle) )
 {
  MessageBox (NULL,"Cannot open the Clipboard","Error",MB_ICONERROR);
   return;
 }

 // Remove the current Clipboard contents
 if( !EmptyClipboard() )
 {
   MessageBox (NULL,"Cannot empty the Clipboard","Error",MB_ICONERROR);
   return;
 }

 // Allocating memory with GlobalAlloc - malloc doesnt work here :p
 // GHND = GMEM_MOVEABLE & GMEM_ZEROINIT
 GLOBALHANDLE hGlobal = GlobalAlloc (GHND |GMEM_SHARE,30);
 int* p = (int*) GlobalLock(hGlobal);   // Pointer to hGlobal


 lstrcpy(p,&(pText.c_str()) ); <---- *** EDO IPARXEI PROVLIMA ***


 // Data format = CF_TEXT (Plain text)
 if ( SetClipboardData(CF_TEXT, p)==NULL)
 {
   MessageBox (NULL,"Unable to set Clipboard data","Error",MB_ICONERROR);
   GlobalUnlock(hGlobal);
   CloseClipboard();
   return;
 }

 GlobalUnlock(hGlobal);
 CloseClipboard();

}

 

Pos mporo na kano antigrapso AnsiString se GLOBALHANDLE ??

Δημοσ.

Το πρόβλημα σου οφείλεται στο γεγονός ότι δηλώνεις ως int (αριθμητικό) τον p pointer (η lstrcpy δέχεται LPCΤSTR) την στιγμή που το AnsiString ως .c_str() επιστρέφει τύπο char (μη άμεσα αριθμητικό) ο οποίος συν της άλλης είναι pointer (άρα δεν χρειάζεται &) στο περιεχόμενο του AnsiString class.

 

Συνεπώς η αλλαγή που ψάχνεις είναι η:

 

>
<..>
char* p = (char*) GlobalLock(hGlobal);   
lstrcpy(p,pText.c_str()); 
<..>

 

Υ.Γ.

Δες και την TClipboard class, ορισμένες φορές είναι αρκετά “flexible” (άλλες πάλι όχι)..

 

Καλή τύχη

Δημοσ.
ok' date=' euxaristo poli ;)

 

Simera xrisimopoiei kaneis winAPI i oloi xirisimopoioun classeis pou ipostirizei o kathe compiler?[/quote']

 

An den kano lathos to VCL tis borland einai win32 wrapper.Opos proanefera ola sto win32API girnan. :)

Δημοσ.
Nai girnane sta API, alla to thema ti xrisimopoioun simera? API i win32 wrappers?

 

Re sy exartate ti thes na kaneis kathe fora , o agorastis tou programmatos pws thelei na to grapseis ktl...Den iparxei genikos kanonas.

Δημοσ.

Simera xrisimopoiei kaneis winAPI i oloi xirisimopoioun classeis pou ipostirizei o kathe compiler?

 

Η πλειοψηφία προτιμά class wrappers (πχ. TClipboard στην περίπτωση της VCL) ή ακόμα και objects (εχμ, components) τρίτων κατασκευαστών αν το εργαλείο ανάπτυξης δεν παρέχει άμεσα βιβλιοθήκη υποστήριξη κάποιας τελευταίας τεχνολογίας (πχ. Bluetooth API) και δεν υπάρχει ή η γνώση ή (και) ο χρόνος για να το κάνουν implement μέσο API εντολών..

 

Για εμένα καλύτερη λύση όλων είναι ο συνδυασμός, δηλαδή να γνωρίζεις το API ώστε να μην δεσμεύεσαι από τις αδυναμίες του προγραμματιστικού εργαλείου σου προσπερνώντας τις όταν είναι αναγκαίο (η VCL όπως και κάθε άλλη βιβλιοθήκη έχει και αυτή περιορισμούς –λίγους είναι η αλήθεια) αλλά να έχεις και την οξυδέρκεια ώστε να το αποφεύγεις όταν δεν έχεις να κερδίσεις κάτι απτό από αυτό (πχ. Καλύτερα να ελέγξεις μια thread μέσο TThread class παρά μέσο API).

 

Υ.Γ.

 

Βέβαια υπάρχει και μια κατηγορία σκληροπυρηνικών που προτιμά να γράφει με το χέρι όταν το πρόγραμμα πρέπει να βγει για κάποιον λόγο (έστω και για μαγκιά) μικρό –ορισμένες φορές είναι αναζωογονητικό ομολογώ... :lol:

 

Καλά Χριστούγεννα σε όλους

Δημοσ.

Μια και είμαστε στο θέμα του CLIPBOARD να πω και το εξής: όποιος βάζει στα NT/XP/2000 ΜΗ UNICODE κείμενο στο Clipboard θα πρέπει να βάζει και το 0x00000408 σαν locale γιατί αλλιώς στο paste βγαίνουν κινέζικα... Βέβαια το πρόβλημα παρακάμπτεται αν ο χρήστης έχει γυρίσει το πληκτρολόγιο στα ελληνικά, αλλά καλύτερα να γίνονται σωστές δουλειές.

 

Στο συγκεκριμένο π.χ. θέμα θέλει οπωσδήποτε API, η VCL δεν το υποστηρίζει.

Δημοσ.

Το συγκεκριμένο πρόβλημα είναι όντως εξαιρετικά ενοχλητικό μιας και δεν υπάρχει μια άμεση παρουσίαση και ανάλυση του ούτε από την βοήθεια των Windows SDK αλλά ούτε και από την πλειοψηφία των σελίδων του διαδικτύου αφού το ζήτημα άπτεται μη λατινογενών ως επί το πλείστο εφαρμογών.

 

Στα πλαίσια αυτά αποφάσισα να ψάξω το ζήτημα κατασκευάζοντας μιας μικρή, συμβατή με τους τύπους της VCL ρουτίνα, που υλοποιεί σωστά την μεταφορά ελληνικών χαρακτήρων στο clipboard προς χρήση κάθε έλληνα προγραμματιστή (μιας και το θέμα είναι λιγάκι περίπλοκο)

 

* Το πρόβλημα έγκειται στο γεγονός ότι όταν στο clipboard των Windows NT/2000/XP τοποθετούμε προγραμματιστικά ένα στοιχείο της μορφής (με την εντολή SetClipboardData δηλαδή) CF_TEXT θα πρέπει πάντα να προηγείται αυτού ένα στοιχείο μορφής CF_LOCALE που να φανερώνει την κωδικοποίηση του CF_TEXT δηλαδή του κειμένου που ακολουθεί.

 

Σε διαφορετική περίπτωση, που δεν παρέχουμε πληροφορία CF_LOCALE πριν την CF_TEXT, (όπως μας πληροφορεί η λακωνική βοήθεια του WinAPI) το σύστημα παρέχει το CF_LOCALE με βάση την ενεργή γλώσσα του πληκτρολογίου μας πράγμα που δεν είναι στην περίπτωση μας επιθυμητό αφού δεν είναι σίγουρο ότι η ενεργή γλώσσα του πληκτρολογίου μας είναι και η σωστή για το CF_TEXT μας!

 

Αυτά είναι σχετικά γνωστά, το ερώτημα που προκύπτει είναι τι μορφή πρέπει να έχει το CF_LOCALE και πως θα συμπεριληφθεί παρέα με το CF_TEXT;

 

Η απάντηση στο πρώτο ερώτημα έρχεται άμεσα από την βοήθεια του WinAPI όπου ορίζεται ως locale identifier πράγμα που μας οδηγεί στο macro MAKELCID για την κατασκευή του.

 

Το δεύτερο ερώτημα είναι εκείνο που ταλαιπωρεί αρκετό «κόσμο» μιας και δεν απαντιέται κατευθείαν αλλά έμμεσα (μιας και η λέξη associated που αναφέρει το WinAPI για το CF_LOCALE μπλέκει τα πράγματα) αφού εδώ θα πρέπει να θυμηθούμε ότι το Clipboard μπορεί να περιέχει όχι μόνο ένα είδος πληροφορίας αλλά πολλά (ουσιαστικά είναι ένας multi buffer χώρος αποθήκευσης) για αυτό και πριν γράψουμε κάτι σε αυτόν καλούμε συνήθως την EmptyClipboard ώστε να τον καθαρίσουμε από κάθε άλλο στοιχείο!

 

Με βάση την παραπάνω παραδοχή το μόνο που πρέπει να κάνουμε είναι δυο ξεχωριστές κλήσεις εγγραφών (δηλαδή OpenClipboard->SetClipboardData->CloseClipboard) σε αυτό δίχως καθαρισμό μεταξύ τους (EmptyClipboard) , όπου η πρώτη θα είναι τύπου CF_LOCALE ενώ η δεύτερη CF_TEXT..

 

Ακολουθεί ο κώδικας σε VCL για ελληνικά (άνετα μπορείτε να τον μετατρέψετε για κάθε γλώσσα και για πέραν της VCL συστήματα καθώς είναι σχεδόν καθαρό WinAPI):

 

>
bool SetClipboardDataGR(AnsiString asText)
{
 HANDLE        hGlobal_Memory,hGlobal_Locale_Memory;
 DWORD         pdwLOCALE;
 char          *pszText;

 if(!OpenClipboard(GetForegroundWindow()))
  {
    ShowMessage("Clipboard CF_LOCALE access denied!");
    return false;
  }

 if(!EmptyClipboard())
  {
    ShowMessage("Cannot empty clipboard!");
    return false;
  }

 //STEP 1: Append CF_LOCALE (GREEK) data to clipboard
 if((hGlobal_Locale_Memory=GlobalAlloc(GHND,sizeof(DWORD)))==NULL)
  {
    CloseClipboard();
    ShowMessage("Not enough memory for this operation!");
    return false;
  }

 if((pdwLOCALE=(DWORD)GlobalLock(hGlobal_Locale_Memory))==NULL)
  {
    CloseClipboard();
    GlobalUnlock(hGlobal_Locale_Memory);
    ShowMessage("Memory lock failure!");
    return false;
  }

 pdwLOCALE=MAKELCID(MAKELANGID(LANG_GREEK,SUBLANG_NEUTRAL),SORT_DEFAULT);
 if(SetClipboardData(CF_LOCALE,hGlobal_Locale_Memory)==NULL)
  {
    CloseClipboard();
    GlobalUnlock(hGlobal_Locale_Memory);
    GlobalFree(hGlobal_Locale_Memory);
    ShowMessage("Clipboard CF_LOCALE transaction faild!");
    return false;
  }

 CloseClipboard();
 GlobalUnlock(hGlobal_Locale_Memory);

 //STEP 2: Append the actual AnsiString data to clipboard as CF_TEXT
 if(!OpenClipboard(GetForegroundWindow()))
  {
    ShowMessage("Clipboard access denied!");
    return false;
  }

 if((hGlobal_Memory=GlobalAlloc(GHND,asText.Length()+1))==NULL)
  {
    CloseClipboard();
    ShowMessage("Not enough memory for this operation!");
    return false;
  }

 if((pszText=(char*)GlobalLock(hGlobal_Memory))==NULL)
  {
    CloseClipboard();
    GlobalUnlock(hGlobal_Memory);
    ShowMessage("Memory lock failure!");
    return false;
  }

 lstrcpy(pszText,asText.c_str());

 if(SetClipboardData(CF_TEXT,hGlobal_Memory)==NULL)
  {
    CloseClipboard();
    GlobalUnlock(hGlobal_Memory);
    GlobalFree(hGlobal_Memory);
    ShowMessage("Clipboard data transaction faild!");
    return false;
  }

 CloseClipboard();
 GlobalUnlock(hGlobal_Memory);


 return true;
}

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.

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