2016-05-24 42 views
1

次のコードを使用して、レジストリのリージョンデータを変更します。再起動せずにレジストリキーを更新するには?

procedure TForm1.Button1Click(Sender: TObject); 
var 
    reg: TRegistry; 
begin 
    reg:=TRegistry.Create; 
    try 
    reg.RootKey:=HKEY_CURRENT_USER; 
    reg.OpenKey('\Control Panel\International\',true); 
    reg.WriteString('iCountry','1'); 
    reg.WriteString('iCurrDigits','2'); 
    reg.WriteString('iCurrency','0'); 
    reg.WriteString('iDate','1');  
    reg.WriteString('iDigits','2');   
    reg.WriteString('iLZero','0'); 
    reg.WriteString('iMeasure','1');  
    reg.WriteString('iNegCurr','0'); 
    reg.WriteString('iNegNumber','1');  
    reg.WriteString('iTimePrefix','0'); 
    reg.WriteString('iTLZero','1');  
    reg.WriteString('Locale','00000409');   
    reg.WriteString('LocaleName','en-US');  
    reg.WriteString('sCountry','United States');  
    reg.WriteString('sDate','/'); 
    reg.WriteString('sDecimal','.');  
    reg.WriteString('iNegCurr','0');  
    reg.WriteString('sShortDate','dd/MM/yyyy'); reg.CloseKey; 
    finally  
    reg.free; 
    end; 
end; 

しかし、変更を有効にするには、マシンを再起動する必要があります。再起動せずに完了できますか?レジストリを変更した後

答えて

2

HWND_BROADCASTへのhWndセットでSendMessageTimeout()を呼び出すことにより、システム全体のWM_SETTINGCHANGEメッセージブロードキャスト:それはそう、

procedure TForm1.Button1Click(Sender: TObject); 
var 
    reg: TRegistry; 
begin 
    reg := TRegistry.Create; 
    try 
    reg.RootKey := HKEY_CURRENT_USER; 
    reg.Access := KEY_SET_VALUE; 
    if reg.OpenKey('\Control Panel\International\', true) then 
    try 
     reg.WriteString('iCountry','1'); 
     reg.WriteString('iCurrDigits','2'); 
     reg.WriteString('iCurrency','0'); 
     reg.WriteString('iDate','1');  
     reg.WriteString('iDigits','2');   
     reg.WriteString('iLZero','0'); 
     reg.WriteString('iMeasure','1');  
     reg.WriteString('iNegCurr','0'); 
     reg.WriteString('iNegNumber','1');  
     reg.WriteString('iTimePrefix','0'); 
     reg.WriteString('iTLZero','1');  
     reg.WriteString('Locale','00000409');   
     reg.WriteString('LocaleName','en-US');  
     reg.WriteString('sCountry','United States');  
     reg.WriteString('sDate','/'); 
     reg.WriteString('sDecimal','.');  
     reg.WriteString('iNegCurr','0');  
     reg.WriteString('sShortDate','dd/MM/yyyy'); 
    finally 
     reg.CloseKey; 
     SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, LPARAM(PChar('intl')), SMTO_NORMAL, 100, PDWORD(nil)^); 
    end; 
    finally  
    reg.free; 
    end; 
end; 

そして、あなたが尋ねる前に:たとえば

Applications should send WM_SETTINGCHANGE to all top-level windows when they make changes to system parameters.

...

wParam
... When the system sends this message as a result of a change in locale settings, this parameter is zero.

When an application sends this message, this parameter must be NULL.

...

lParam
... When the system sends this message as a result of a change in locale settings, this parameter points to the string "intl".

をこの方法で最後のパラメータにnilを使用することは安全です:

Passing nil to a variable parameter

XE2に先立ち、DelphiのWindows単位はようSendMessageTimeout()の最後のパラメータを宣言します。

var lpdwResult: DWORD 

しかし、Win32 APIがなどのパラメータを定義しています

NULLポインタがあることを可能にする
_Out_opt_ PDWORD_PTR lpdwResult 

上記のnilトリックは、デルファイコードがvarパラメータにNULL値を渡す唯一の方法です。コンパイラによって生成されたマシンコードは正しいでしょう - 単にパラメータに0の値を渡すだけで、実際にはメモリアドレス$ 00000000にアクセスしません。 Win32 APIの定義を一致させるには

lpdwResult: PDWORD_PTR 

:XE2では

は、Windowsユニットは次のように最後のパラメータを宣言するために変更されました。

コードをXE2以降にアップグレードする場合は、PDWORD(nil)^を代わりにnilに置き換えてください。それとも、あなたは後でそれを心配し、今ではなく、それを説明することができる:

SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, LPARAM(PChar('intl')), SMTO_NORMAL, 100, {$IF RTLVersion >= 23}nil{$ELSE}PDWORD(nil)^{$IFEND}); 
+0

を、私はあなたの既存のコードのエラーを使用します。実際の正式のvarパラメータの種類はあきらめる、またはコードを読むのいずれか –

+1

@Ahmad同一である必要がありますエラーを理解し、修正する方法を解説します。誰かが答えにいくつかのコードを書いているだけで、そこにコードを転送するときにプログラムをデバッグする必要があるということを意味しません。エラーメッセージはクリアです。わかりますか? –

+0

最も可能性の高い説明は、SendMessageTimeoutの最終引数です。 Windows.pasの宣言を読んで、うまくいくかどうか確認してください。 –

関連する問題