ロケールを和暦に変更するには?


やまだ  2014-11-06 00:56:39  No: 46862

こんにちは。

いつもお世話になっております。

開発環境は、delphiXE3 enterprise(update2適用)、win7(sp1)です。

DateTimePickerとかMonthCalendarを使おうと考えています。

いま、すごく悩んでいます。

プログラムが起動するとき、現在のロケールを取得して、ロケールを和暦にして。

プログラムが終了するとき、取得したロケールをセットする。

プログラムが起動している最中、ロケールを一時的に変更して、カレンダーを和暦にしようと思っています。

こういったことは可能でしょうか?

GetLocaleInfoとSetLocaleInfoを使えば良いかもというのは大方判ったのですが、実際どう使えば良いかが分かりません。

ご存知の方教えてください。

よろしくお願いします。


通りすがり  2014-11-06 01:53:37  No: 46863

ロケールという言葉の意味を誤解されているような気がしますが、それはさておき、ご所望のものは

System.SysUtils.FormatSettings
http://docwiki.embarcadero.com/Libraries/XE3/ja/System.SysUtils.FormatSettings

System.SysUtils.TFormatSettings
http://docwiki.embarcadero.com/Libraries/XE3/ja/System.SysUtils.TFormatSettings

ではないでしょうか?プログラムの最初(メインフォームのOnCreateあたり)で
System.SysUtils.FormatSettings.LongDateFormat := 'ggE年mm月dd日';
とかで。


やまだ  2014-11-06 19:00:07  No: 46864

なにぶん、こういったものはやったことがなかったので、随分悩んでいましたが、何となく出来るような気がしてきました。

TFormatSettingsで色々調べました。

読み込めばrecord体に格納されるみたいで、record体の中のデータを実際コードを書いて見てみました。

でも残念ながら、カレンダーの種類を表すデータがありませんでした。

カレンダーの種類を「西暦(日本語)」から「和暦」に変更したいと思っています。

TFormatSettingsで読めないとなると、何のクラスになるのでしょうか?

よろしくお願いします。


deldel  2014-11-06 19:35:53  No: 46865

色々苦労されているようですが、こういう場合は自作した方が
結局は速かったりします。
私も昔、色々あって作ったことがあります。
かなり昔のコード(D3で作成?)ですが、一応全ソース載せてみます。
和暦表示はしていませんが(^^;

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Spin, Grids;

type
  TForm1 = class(TForm)
    SeYear: TSpinEdit;
    SeMonth: TSpinEdit;
    StringGrid1: TStringGrid;
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure SeMonthChange(Sender: TObject);
    procedure SeYearChange(Sender: TObject);
    procedure StringGrid1Click(Sender: TObject);
  private
    { Private 宣言 }
    procedure pSetCalender(saYear, saMonth: AnsiString);
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
  StringGrid1.RowCount := 7;
  StringGrid1.ColCount := 7;
  StringGrid1.FixedCols := 0;
  StringGrid1.FixedRows := 1;
  StringGrid1.Cells[0, 0] := '日';
  StringGrid1.Cells[1, 0] := '月';
  StringGrid1.Cells[2, 0] := '火';
  StringGrid1.Cells[3, 0] := '水';
  StringGrid1.Cells[4, 0] := '木';
  StringGrid1.Cells[5, 0] := '金';
  StringGrid1.Cells[6, 0] := '土';
  SeYear.Value := StrToInt(FormatDateTime('yyyy', Now));
  SeMonth.Value := StrToInt(FormatDateTime('m', Now));
  pSetCalender(IntToStr(SeYear.Value), IntToStr(SeMonth.Value));
end;

procedure TForm1.pSetCalender(saYear, saMonth: AnsiString);
  function f_ibGetLastDayOfMonth(Year, Month : integer) : Byte;
  const
    DaysInMonth: array[1..12] of Integer = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
  begin
    if (IsLeapYear(Year) = True) and (Month = 2) then
      Result := 29
    else
      Result := DaysInMonth[Month];
  end;
var
  saDay: AnsiString;
  x, y: Byte;
  ibTuitatiYobi: Byte;
  ibDate: Byte;
  ibLastDayOfMonth: Byte;
begin
  ibTuitatiYobi := DayOfWeek(StrToDate(saYear + '/' + saMonth + '/1')) - 1;
  ibLastDayOfMonth := f_ibGetLastDayOfMonth(StrToInt(saYear), StrToInt(saMonth));

  ibDate := 0;
  for y := 1 to 6 do begin
    for x := 0 to 6 do begin
      if (y = 6) and (x = 2) then Break;

      if (y = 1) and (x < ibTuitatiYobi) then begin
        saDay := '';
      end else

      if ibDate = ibLastDayOfMonth then begin
        saDay := '';
      end else

      begin
        inc(ibDate);
        saDay := IntToStr(ibDate);
      end;

      StringGrid1.Cells[x, y] := saDay;
    end;
  end;
end;

procedure TForm1.SeMonthChange(Sender: TObject);
begin
  pSetCalender(IntToStr(SeYear.Value), IntToStr(SeMonth.Value));
end;

procedure TForm1.SeYearChange(Sender: TObject);
begin
  pSetCalender(IntToStr(SeYear.Value), IntToStr(SeMonth.Value));
end;

procedure TForm1.StringGrid1Click(Sender: TObject);
var
  saYear, saMonth, saDay: AnsiString;
  dt: TDateTime;
begin
  saDay := Trim(StringGrid1.Cells[StringGrid1.Col, StringGrid1.Row]);
  if saDay <> '' then begin
    saYear := IntToStr(SeYear.Value);
    saMonth := IntToStr(SeMonth.Value);
    showmessage(saYear + '/' + saMonth + '/' + saDay);

    dt := StrToDate(saYear + '/' + saMonth + '/' + saDay);
    showmessage(FormatDateTime('gge"年"m"月"d"日"', dt));
  end;
end;

end.


やまだ  2014-11-07 21:05:40  No: 46866

カレンダーを作成した方が良いのでしょうか。

カレンダーの種類は、やはり取得できないのでしょうか?

お願いします。


通りすがり  2014-11-07 21:47:01  No: 46867

カレンダーの種類、というのはありません。カレンダーがどの形式で日付を扱うのか、は、システムの設定に依存します。


やまだ  2014-11-07 22:48:50  No: 46868

コントロールパネルを見ていて、カレンダーの種類となっていたので、書いてしまいました。

システムの設定を読み込んだとして、コントロールパネルのカレンダーの種類は変数に入らないのでしょうか?

よろしくお願いします。


通りすがり2  2014-11-07 23:58:42  No: 46869

>カレンダーの種類、というのはありません。

読めませんか?


やまだ  2014-11-08 00:26:34  No: 46870

こんにちは。

こちらのサイト(http://www1.kokusaika.jp/advisory/org/ja/common_culture_exp.html)を見て
以下のようなコードを実行してみました。

LOCALE_ICALENDARTYPEは以下を参考にしました。

http://msdn.microsoft.com/en-us/library/aa912934.aspx

実行したコード:
SetLocaleInfo(LOCALE_SYSTEM_DEFAULT,LOCALE_ICALENDARTYPE,PChar('2'));

実行した結果は読み取り違反のエラーメッセージが出ました。

まだGetLocaleInfoで取得というのはやっていないのですが、サイトに書いてあったんですが、SetLocaleInfoでは書き込みができないのでしょうか?

よろしくお願いします。


tor  2014-11-08 01:24:10  No: 46871

なんか話が噛み合っていないようなので……

通りすがりさん、「カレンダーの種類」という設定は、日付の書式設定とは別にちゃんと存在します。
ラヲサキの場合だと以下の手順で出てきます。
ィアゥヲサコントロールパネルの「地域と言語」を開く
ィイゥヲサ最初の「形式」タブ(日付書式の設定があるところ)の下の方にある「追加の設定」ボタンを押す
ィウゥヲサ「形式のカスタマイズ」ダイアログが出てくるので、「日付」タブを選択する
ィエゥヲサ下の方の「カレンダー」グループの中に「カレンダーの種類」発見!

デフォルトだと「西暦(日本語)」になっていますが、これを「和暦」に変更してマヒすると……
万歳!ヲサトヤミでも和暦で表示・選択ができるようになったぞ!

でもこれだとユーザのシステム設定が変わってしまうことになるので、当然ながらよろしくない。
せめて自分のプログラムが起動している間だけ一時的に変更できないか
(理想的にはトヤミにだけ適用できないか)、というのがやまださんの求めていることですよね。

次にニモについて。
なんかやまださんはしきりに「読む」と言っていますが、今回の目的には別に中身を読む必要なんてなくて
通りすがりさんの提示したコード例のとおり、該当するフィールドを書き換えればいいだけです。
それだけで「自分のプログラムにだけその設定が適用される」という望みどおりの動作になる……のです、まあ運が悪くなければ。

今回これは二つの理由でうまくいきません。
アョヲサ前述の「カレンダーの種類」に対応するフィールドはヤニモに含まれていない。
イョヲサトヤミなどはラのテヲサをラップしたものであって
トの書式変換ルーチンを使用しているわけではないため、ニモを変更しても影響を受けない。

偉そうなこと言ってるけど、じゃあどうやって解決するんだって?ヲサふふふ、よくぞ聞いてくれました(今急いで調べてきた)
ヘテコントロールにはちゃんとカレンダーの種類を選ぶためのメッセージが用意されているのです。

ヲサモヘィヘテアョネャヲサヘテペモナヤテチフノトャヲサテチプハチミチホャヲサーゥサ

どやっ!ヲサ……ってあれれ、効果がないぞ?ヲサうむむ、出直して参ります……
スススススススススススススススススススススススススススススススススススススススス
ニコ やまだ
トコ イーアエッアアッーキィ金ゥ アカコオケコウカ  書込者ノト:ロ 「。「 「「 ン

やりたかったことは、さんが仰ってらっしゃる通りです。

さきほども書きましたが、ヌフノで試してみました。

結果は、読み取れました。

コンパネで「西暦(日本語)」を設定した場合「ア」が取得でき、「和暦」を設定した場合「ウ」が取得できました。

読み取り値はこちら↓を参考にしてください。
コッッョョッュッッケアイケウエョ

これでモフノで書き込みさえ出来れば、
「ア」だったら「ウ」
「ウ」だったら「ア」
のように起動時に設定できます。

でも、どうしてもモフノで読み取り違反エラーが出てしまいます。
スススススススススススススススススススススススススススススススススススススススス
ニコ 
トコ イーアエッアアッーキィ金ゥ アキコウキコーイ  書込者ノト:ロ 」 ァ」ハノ

 ン

ヲサヲサモフノィフマテチフナ゜モルモヤナペトナニチユフヤャフマテチフナ゜ノテチフナホトチメヤルミナャミティァイァゥゥサ

これだとヲサァイァヲサがモじゃなくテ型なので
ミティノィ」ネウイゥゥヲサと解釈され、ーーーーーーーウイヲサというアドレスになってしまっていますね。
文字列のアドレスを渡すつもりなら、いったんモに入れましょう……

ヲサコヲサモサ
ョョョ
ヲサコスヲサァイァサ
モフノィョョョャヲサミティゥゥサ
スススススススススススススススススススススススススススススススススススススススス
ニコ やまだ
トコ イーアエッアアッアアィ火ゥ ーケコウウコイケ  書込者ノト:ロ 「。「 「「 ン
モコ 

なるほど。
確かにそうですね。

上手く行きました。

ありがとうございました。

ただ、プログラム起動時に西暦→和暦に変換したりして起動した場合、の右下のカレンダーの表示が変な感じになったりします。

通常は平成ヲサイカッアアッアアのような表示なのですが、イカッアアッアアのような表示になります。

でも目的のものは出来ましたし、プログラム起動時の一時的なものなので、とりあえず様子を見ます。

いろいろありがとうございました。
スススススススススススススススススススススススススススススススススススススススス
ニコ 
トコ イーアエッアアッアアィ火ゥ アーコアオコアエ  書込者ノト:ロ ァ。   ン

単にカレンダーの種類を和暦に変更しただけだと、短い形式、長い形式に元号が無い状態になるからでしょう。
カレンダーの種類だけで無く、短い形式、長い形式も一緒に変更したら良いかと思います。

ヲサヲサモフノィフマテチフナ゜ユモナメ゜トナニチユフヤャヲサフマテチフナ゜ノテチフナホトチメヤルミナャヲサァウァゥサ
ヲサヲサモフノィフマテチフナ゜ユモナメ゜トナニチユフヤャヲサフマテチフナ゜モモネマメヤトチヤナャヲサァヲサッヘッァゥサ
ヲサヲサモフノィフマテチフナ゜ユモナメ゜トナニチユフヤャヲサフマテチフナ゜モフマホヌトチヤナャヲサァヲサァァ年ァァヘァァ月ァァァァ日ァァァゥサ
ヲサヲサモヘヤィネラホト゜ツメマチトテチモヤャヲサラペモナヤヤノホヌテネチホヌナャヲサーャヲサーャヲサモヘヤマ゜ホマメヘチフャヲサオーーャヲサホゥサ


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加