CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Windows 7 - program napisany w BCB 6.0 - format daty
Strona 1 z 1

Windows 7 - program napisany w BCB 6.0 - format daty

Nowy postNapisane: czwartek, 4 listopada 2010, 17:30
przez scorp1on
Witam
Jest program napisany w BCB 6.0, po uruchomieniu w Windows 7 pojawia się błąd związany z formatem daty, pomimo ustawień w panelu sterowania na polskę program wyświetla amerykański format stąd są problemy. Ten sam program uruchomiony na Viście działa ok. Czy jest na to jakiś sposób aby program ustawił odpowiednio lokalizację pod Windows 7. Problem dotyczy też wyświetlania waluty jest dolar zamiast złotówki.

Re: Windows 7 - program napisany w BCB 6.0 - format daty

Nowy postNapisane: czwartek, 4 listopada 2010, 17:58
przez Cyfrowy Baron
Podaj kod, którego używasz do wyświetlania daty.



Tutaj masz kod pokazujący jak to można zrobić pobierając format daty i czasu ustawiony w systemie:

KOD cpp:     UKRYJ  
 TFormatSettings fSettings;
 GetLocaleFormatSettings(1045, fSettings);
 TDateTime  DateTime = Now();
 Edit1->Text = DateTime.FormatString(fSettings.LongDateFormat +  " " + fSettings.LongTimeFormat);



GetLocaleFormatSettings(LCID: Integer; var FormatSettings: TFormatSettings);



LCID - lokalny kod języka - polska 1045. Jeżeli wprowadzisz niewłaściwy, to niezależnie od formatowania zdefiniowanego w systemie, data zostanie uporządkowana w sposób typowy dla danego języka. Porównaj z kodem 1033 - USA.

TFormatSettings - struktura do której funkcja zwróci ustawienia zdefiniowane w systemie. Struktura przechowuje następujące ustawienia:


TFormatSettings :
Byte CurrencyFormat;
Byte NegCurrFormat;
Char ThousandSeparator;
Char DecimalSeparator;
Byte CurrencyDecimals;
Char DateSeparator;
Char TimeSeparator;
Char ListSeparator;
String CurrencyString;
String ShortDateFormat;
String LongDateFormat;
String TimeAMString;
String TimePMString;
String ShortTimeFormat;
String LongTimeFormat;
TFormatSettings.:1 ShortMonthNames;
TFormatSettings.:2 LongMonthNames;
TFormatSettings.:3 ShortDayNames;
TFormatSettings.:4 LongDayNames;
WORD TwoDigitYearCenturyWindow;



Jeżeli chodzi o te elementy struktury:


TFormatSettings.:1 ShortMonthNames;
TFormatSettings.:2 LongMonthNames;
TFormatSettings.:3 ShortDayNames;
TFormatSettings.:4 LongDayNames;



To nie wiem jak je stosować, ale chętnie bym się dowiedział.

Re: Windows 7 - program napisany w BCB 6.0 - format daty

Nowy postNapisane: czwartek, 4 listopada 2010, 20:54
przez scorp1on
Cyfrowy Baron napisał(a):Podaj kod, którego używasz do wyświetlania daty.


Używam w BCB 6 funkcji Date(); zwraca na Viście/XP ciąg "2010-11-04", w przypadku Windows 7 zwraca "11/04/2010"
W przypadku BCB 2010 tego problemu nie ma na obu systemach funkcja Date() zwraca "2010-11-04".

Dzięki za pomoc.

Różne sposoby formatowania daty i czasu - TDateTime

Nowy postNapisane: piątek, 5 listopada 2010, 10:04
przez Cyfrowy Baron
Używasz po prostu funkcji Date() w ten np. sposób:

KOD cpp:     UKRYJ  
 Edit1->Text = Date();

W ten sposób na ogół wyświetlona zostanie data krótka ustawiona w systemie. By jednak mieć pewność, że zawsze tak będzie, należałoby to zrobić tak:

KOD cpp:     UKRYJ  
 TFormatSettings fSettings;
 GetLocaleFormatSettings(1045, fSettings);
 Edit1->Text = Date().FormatString(fSettings.ShortDateFormat);

Datę podobnie jak czas możesz też formatować po swojemu, np:

KOD cpp:     UKRYJ  
 Edit1->Text = Date().FormatString("dddd dd mmmm yyyy");
 Edit2->Text = Time().FormatString("hh-nn-ss");
 Edit3->Text = TDateTime::CurrentDateTime().FormatString("dd-mmmm-yyyy hh-nn-ss");;

Możesz również wstawiać dowolny tekst między formatowaną datę, ale ów tekst musi być ujęty w apostrofy:

KOD cpp:     UKRYJ  
 Edit1->Text = Date().FormatString("'dziś jest' dddd 'dnia' dd ', miesiąca' mmmm ', roku' yyyy");

KOD cpp:     UKRYJ  
 TFormatSettings fSettings;
 GetLocaleFormatSettings(1045, fSettings);
 Edit1->Text = Date().FormatString("'Aktualna data: '" + fSettings.ShortDateFormat);

Do pobrania aktualnej daty masz jeszcze funkcję Now():

KOD cpp:     UKRYJ  
 TFormatSettings fSettings;
 GetLocaleFormatSettings(1045, fSettings);

 Edit1->Text = Now();

 Edit2->Text = Now().FormatString("'Aktualna data: '" + fSettings.ShortDateFormat);
 Edit3->Text = Now().FormatString("'Aktualny czas: '" + fSettings.LongTimeFormat);

 Edit4->Text = Now().FormatString("'Dziś jest:' dd-mm-yyyy");
 Edit5->Text = Now().FormatString("'Godz.:' hh:nn:ss");
oraz funkcję TDateTime::CurrentDate():

KOD cpp:     UKRYJ  
void __fastcall TForm1::Button1Click(TObject *Sender)
{
 TFormatSettings fSettings;
 GetLocaleFormatSettings(1045, fSettings);

 TDate Today = TDate::CurrentDate();

 Edit1->Text = Today;
 Edit2->Text = Today.FormatString("'Aktualna data: '" + fSettings.ShortDateFormat);
}
Dla czasu masz odpowiednio: TDateTime::CurrentTime(), a dla daty i czasu - TDateTime::CurrentDateTime().
Jeżeli tworzysz obiekt tylko typu TDate, to zwróci on tylko datę, podobnie jak TTime zwróci tylko czas. Jeżeli potrzebujesz jednocześnie daty i czasu, to należy użyć typu TDateTime:

KOD cpp:     UKRYJ  
void __fastcall TForm1::Button1Click(TObject *Sender)
{
 TFormatSettings fSettings;
 GetLocaleFormatSettings(1045, fSettings);

 TDateTime Today = TDateTime::CurrentDateTime();

 Edit1->Text = Today;
 Edit2->Text = Today.FormatString("'Aktualna data: '" + fSettings.ShortDateFormat);
 Edit3->Text = Today.FormatString("'Aktualny czas: '" + fSettings.LongTimeFormat);
 Edit4->Text = Today.FormatString("'Dziś jest: '" + fSettings.ShortDateFormat +
                                  "' godz.: '" + fSettings.LongTimeFormat);
}


Można też po prostu tak:

KOD cpp:     UKRYJ  
 Edit1->Text = TDate::CurrentDate().FormatString("dd-mm-yyyy");
 Edit2->Text = TTime::CurrentTime().FormatString("hh:nn:ss");
 Edit3->Text = TDateTime::CurrentTDateTime().FormatString("dddd dd mmmm yyyy',' hh:nn:ss");




Tutaj ciekawe spostrzeżenie, jeżeli użyjesz typy TDate z TDate::CurrentTime(), to pomimo iż TDate zwraca datę, to zwróci również czas:

KOD cpp:     UKRYJ  
 TDate Today = TDate::CurrentTime();


Podobnie z TTime:

KOD cpp:     UKRYJ  
 TTime Today = TTime::CurrentDate();


Nie polecam jednak takich kombinacji, gdyż nigdy nie wiadomo co z tego wyniknie.

Re: Windows 7 - program napisany w BCB 6.0 - format daty

Nowy postNapisane: piątek, 5 listopada 2010, 10:46
przez scorp1on
Jaką bibliotekę trzeba dołączyć aby to w BCB 6 zadziałało.
mam błąd

[C++ Error] Unit1.cpp(31): E2451 Undefined symbol 'TFormatSettings'
[C++ Error] Unit1.cpp(31): E2379 Statement missing ;
[C++ Error] Unit1.cpp(32): E2268 Call to undefined function 'GetLocaleFormatSettings'
[C++ Error] Unit1.cpp(32): E2451 Undefined symbol 'fSettings'


Re: Windows 7 - program napisany w BCB 6.0 - format daty

Nowy postNapisane: piątek, 5 listopada 2010, 10:51
przez Corvis
Weź kod wklej :-)

bo tutaj pokazuje, że średnik zjadłeś.


Edit. TFormatSettings jest w Unicie SysUtils

Re: Windows 7 - program napisany w BCB 6.0 - format daty

Nowy postNapisane: piątek, 5 listopada 2010, 10:52
przez Cyfrowy Baron
Struktura jest zdefiniowana w bibliotece SysUtils.hpp, ale muszę to jeszcze sprawdzić dla BCB 6.

Re: Windows 7 - program napisany w BCB 6.0 - format daty

Nowy postNapisane: piątek, 5 listopada 2010, 11:13
przez Cyfrowy Baron
Z tego co zdążyłem się zorientować to w BCB6 nie ma funkcji GetLocaleFormatSettings i struktury TFormatSettings, więc potrzebne jest inne rozwiązanie. Gdy coś wymyślę dam znać, chociaż będzie trudno gdyż nie mam dostępu do BCB6.

Ustawienia daty i czasu poprzez funkcję GetLocaleInfo.

Nowy postNapisane: piątek, 5 listopada 2010, 12:07
przez Cyfrowy Baron
Proponuję skorzystać z funkcji GetLocaleInfo, powinna być dostępna w BCB6:
KOD cpp:     UKRYJ  
 char longDate[255];
 GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SLONGDATE, longDate, sizeof(longDate));

 char shortDate[11];
 GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SSHORTDATE, shortDate, sizeof(shortDate));

 char longTime[9];
 GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STIMEFORMAT, longTime, sizeof(longTime));



 Edit1->Text = Date().FormatString("'Aktualna data: '" + (String)longDate);

 Edit2->Text = TDateTime::CurrentDateTime().FormatString("'Dzień: '" +
                        (String)shortDate + "', godz.: '" + (String)longTime);

 Edit3->Text = Time().FormatString("'Aktualna godz.: '" + (String)longTime);




Pytanie do polymorphism: czy dałoby się jakoś zastąpić zmienną char tak by nie trzeba było określać z góry jej rozmiaru, lecz tak by sama dopasowywała sobie rozmiar?! :roll:

Re: Windows 7 - program napisany w BCB 6.0 - format daty

Nowy postNapisane: piątek, 5 listopada 2010, 19:14
przez polymorphism
KOD cpp:     UKRYJ  
int cch = GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STIMEFORMAT, 0, 0);
if(cch > 0)
{
        vector<TCHAR> buf(cch);
        cch = GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STIMEFORMAT, &buf[0], buf.size());
        if(cch > 0)
        {
                cout << &buf[0] << '\n';
        }
}
 

O to chodzi?

Z drugiej strony, format daty jest raczej mały, więc nie wiem, czy jest sens się tak bawić, w tablicy 255-elementowej spokojnie się zmieści.

Re: Windows 7 - program napisany w BCB 6.0 - format daty

Nowy postNapisane: sobota, 6 listopada 2010, 09:01
przez Cyfrowy Baron
Nie o to mi chodziło, lecz żeby tak jak w przypadku typy AnsiString, nie podawać rozmiaru bufora typu char, czyli nie określać z góry rozmiaru na 255, gdyż teoretycznie w przypadku LOCALE_SLONGDATE ten rozmiar może być większy. Tak naprawdę jednak jestem ciekaw czy dałoby się coś takiego z tym zrobić.

Zauważyłem, że funkcja GetLocaleInfo odczytuje dane z rejestru, więc można by stworzyć własną pobierającą te dane właśnie z rejestru i zbudować ja na typie AnsiString, a nie char.

Re: Windows 7 - program napisany w BCB 6.0 - format daty

Nowy postNapisane: sobota, 6 listopada 2010, 11:24
przez polymorphism
Nie o to mi chodziło, lecz żeby tak jak w przypadku typy AnsiString, nie podawać rozmiaru bufora typu char, czyli nie określać z góry rozmiaru na 255

W przykładzie z vectorem nie musisz określać rozmiaru na sztywno, więc o co chodzi? Czytać bezpośrednio do AnsiStringa też nie możesz. Jedyne co możesz zrobić, to stworzyć bufor o wymaganej wielkości, wywołać funkcję i przepisać zawartość bufora do stringa.


(...) gdyż teoretycznie w przypadku LOCALE_SLONGDATE ten rozmiar może być większy.

U mnie ma 12 bajtów.





Do małych, tymczasowych alokacji można użyć funkcji alloca, która przydziela pamięć ze stosu, dzięki czemu alokacja jest szybsza i zapobiega fragmentacji pamięci:
KOD cpp:     UKRYJ  
int cch = GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SLONGDATE, 0, 0);
if(cch > 0)
{
        TCHAR* buff = (TCHAR*)alloca(sizeof(TCHAR) * cch); // równoznaczne z niestandardowym TCHAR buff[cch];
               
        cch = GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SLONGDATE, buff, cch);
        if(cch > 0)
        {
                cout << buff << '\n';
        }
}

Pamięci przydzielonej tą funkcją nie można zwalniać, ponieważ, jak wcześniej pisałem, jest ona pamięcią stosu. Dodatkowo pamięć ta ma zasięg lokalny, tak samo jak zwykła tablica zdefiniowana lokalnie, zatem nie można jej zwracać jako wynik działania funkcji. Ogólnie rzecz biorąc, ostrożnie z tą metodą alokacji pamięci.