Frage

Was?

Ich habe eine DLGTEMPLATE von einem Ressource-DLL geladen, wie kann ich die Saiten auf die Steuerelemente zur Laufzeit zugewiesen ändern programmatisch?

Ich möchte in der Lage sein, dies zu tun, bevor der Dialog erstellt wird, so dass ich sagen kann, dass die Saiten auf dem Display von den Ressourcen-DLL kamen und nicht von Anrufen auf SetWindowText, wenn der Dialog initialisiert wird.

Google Beispiele für das Erstellen DLGTEMPLATE im Code gefunden hat, oder einfach Stil Bits aber nichts twiddling zur Bearbeitung der Strings im Speicher.

Wie?

Ich tue dies, indem Sie den Dialog / Property Sheet Erstellung API Einhaken. Das gibt mir Zugang zu der DLGTEMPLATE vor dem eigentlichen Dialog erstellt wird und bevor es eine HWND hat.

Warum?

Ich möchte in der Lage sein Laufzeit-Lokalisierung zu tun, und Lokalisierungstests. Ich habe bereits diese für das Laden String implementiert haben (einschließlich der MFC 7.0-Wrapper), Menüs und Beschleuniger Tabellen, aber ich habe Schwierigkeiten dialog / Eigenschaftsfenster Erstellung zu behandeln.

Code-Beispiele wären die perfekte Antwort, idealerweise eine Klasse um die DLGTEMPLATE zu wickeln, wenn ich, dass ich meine eigene Lösung funktionieren werde es schreiben.

War es hilfreich?

Lösung

Sie können die Strings im Speicher bearbeiten. Die DLGTEMPLATE Struktur ist eine direkte Zuordnung der Datei relevent Bytes der Ressource-DLL. Das ist nur lesen.

Sie gehen zu müssen, die gesamte DLGTEMPLATE Struktur verarbeiten und einen neuen mit den veränderten Zeichenfolge schreiben.

Es wird ehrlich gesagt einfacher sein, nur die WM_INITDIALOG Haken und die Saiten verändern, indem sie mit den Kontrollen der Interaktion als einen DLGTEMPLATE Schriftsteller zu bauen. Da es arn't viele Menschen in Ihrer Umgebung. Sofern Sie eine zusätzliche Anforderung haben, um tatsächlich veränderte Dialog Ressourcen auf der Festplatte als rohes .res Dateien (oder versuchen, den DLL-Inplace zu ändern) zu speichern Id wirklich empfehlen Sie diesen Ansatz zu vermeiden.

Sie sagen, Sie sind bereits diese Zeichenfolge für Accellerator Tabellen und Menü zu tun - wenn Sie garantieren können, dass die in Strings gepatcht werden kürzer, dann nur eine binäre Kopie der DLGTEMPLATE Struktur machen, und die nicht trivial Scan-Code schreiben notwendig, jede Zeichenfolge zu finden, so dass Sie die Kopie anstelle flicken können.

Andere Tipps

Es gibt eine Datei irgendwo heraus (was ich bei Microsoft entstanden denken, aber ich bin nicht ganz sicher) genannt RESFMT.ZIP, die dies mit einigen Codebeispielen erläutert. Raymond Chen hat auch einige gute Erklärungen für diese in seinem Blog. Beachten Sie, dass das Format der DIALOGEX und DIALOG Kontrollen sind unterschiedlich.

Wie in einigen anderen Antworten darauf hingewiesen, würden Sie brauchen, um die Struktur wieder von Anfang an zu schaffen. Das ist nicht alles schlecht, wie Sie bereits die grundlegenden Informationen haben. Das Hinzufügen der Kontrollen ist, wo wird hart ist.

Grundsätzlich weisen Sie einen largish Speicherblock in einen WORD * LPIN. Dann fügen Sie die Struktur nach oben obendrein. die grundlegenden Informationen für den Dialog hinzugefügt werden (siehe DLGTEMPLATE) und die Kontrollen ist ziemlich offensichtlich, wie die Informationen gibt es in MSDN.

Die beiden größten Probleme begegnen Sie sind: Sicherzustellen, dass die verschiedenen Teil Start auf einer Ausrichtungsgrenze, und die Werte von DIALOG Kontrollen zu interpretieren, vor allem, wenn eine nur einen String oder eine Zeichenfolge oder Ordnungs hinzuzufügen. Jede Kontrolle muss auf einer ebenen Grenze starten.

Für die erste (entlehnt von irgendwo Ich denke RESFMT.ZIP):

WORD *AlignDwordPtr (WORD *lpIn)
    {
    ULONG ul;

    ul = (ULONG) lpIn;
    ul +=3;
    ul >>=2;
    ul 

What I did was build a series of functions like this one following that allowed me to assemble DIALOGS in memory. (My need was so I could have some common code that didn't need an associated RC file for some very basic messages).

Here is an example...

WORD *AddStringOrOrdinalToWordMem( WORD *lpw, char    *sz_Or_Ord )
    {
    LPWSTR  lpwsz;
    int     BufferSize;

    if (sz_Or_Ord == NULL)
        {
        *lpw++ = 0;
        }
    else
        {
        if (HIWORD(sz_Or_Ord) == 0) //MAKEINTRESOURCE macro 
            {
            *lpw++ = 0xFFFF;
            *lpw++ = LOWORD(sz_Or_Ord);
            }
        else
            {
            if (strlen(sz_Or_Ord))
                {
                lpwsz = ( LPWSTR ) lpw;
                BufferSize = MultiByteToWideChar( CP_ACP, 0, sz_Or_Ord, -1, lpwsz, 0 );
                MultiByteToWideChar( CP_ACP, 0, sz_Or_Ord, -1, lpwsz, BufferSize );
                lpw = lpw +  BufferSize;
                }
            else
                {
                *lpw++ = 0;
                }
            }
        }
    return( lpw );
    }

The header file to the complete module included these functions:

WORD *AddControlToDialogTemplateEx(MTDialogTemplateType *dlgtmp, char *Title, WORD Id, char *WinClass, DWORD Style, short x, short y, short cx, short cy, DWORD ExStyle, int HelpID); int DestroyDlgTemplateEx(MTDialogTemplateType *dlgtmp); MTDialogTemplateType *CreateDlgTemplateEx( char *Name, // We use name just for reference, so it can be NULL short x, short y, short cx, short cy, DWORD ExtendedStyle, DWORD Style, char *Menu, char *WinClass, char *Caption, char *FontTypeFace, int FontSize, int FontWeigth, int FontItalic, int Charset, int HelpID, int NumberOfControls);

Was mir erlaubt, von Code ganze Dialoge leicht zu montieren ist.

Sehen Sie die API-Funktion :: EnumChildWindows (HWND, WNDENUMPROC, LPARAM)

Sie können dies nennen in einem CFormView :: Create oder CDialog :: OnInitDialog Sie sich eine Chance zu geben, die Kontrolle Bildunterschriften zu ersetzen. Keine Sorge, nicht auf die alten Saiten flackern, bevor Sie sie ersetzen.

In Ihrer Dialogressource, stellen Sie die Steuer Bildunterschriften zu einem Schlüssel in einer Art Wörterbuch. Wenn Sie kompilieren / clr können Sie einen verwalteten String-Tabelle Ressource verwenden. In Ihrem Rückruf, schauen die übersetzte Zeichenfolge in Ihrem Wörterbuch und setzt die Beschriftung der Steuerung an die Übersetzung. Ein weiterer Vorteil der / clr und String-Tabelle verwaltet ist, dass Sie automatisch die richtige Sprache, die von Windows-nachschlagen können (oder Sie) haben bereits eingestellt System :: Threading :: Thema :: CurrentThread-> CurrentUICulture.

So etwas

CMyDialog::OnInitDialog()
{
    ::EnumChildWindows(
        this->GetSafeHwnd(),
        CMyDialog::UpdateControlText,
        (LPARAM)this )
}

BOOL CALLBACK CMyDialog::UpdateControlText( HWND hWnd, LPARAM lParam )
{
    CMyDialog* pDialog = (CMyDialog*)lParam;
    CWnd* pChildWnd = CWnd::FromHandle( hWnd );

    int ctrlId = pChildWnd->GetDlgCtrlID();
    if (ctrlId)
    {
        CString curWindowText;
        pChildWnd->GetWindowText( curWindowText );
        if (!curWindowText.IsEmpty())
        {
            CString newWindowText = // some look up
            pChildWnd->SetWindowText( newWindowText );
        }
    }
}

Sie werden die Zeichenfolge gefunden haben, müssen Sie im mem Puffer ändern möchten, der die Vorlage darstellt. Der einzige Weg, das zu tun ist, um die ganze Vorlage zu durchqueren. Welche ist nicht einfach. Sobald Sie das getan haben, entweder einfügen Bytes in dem Puffer, wenn Ihre neue Zeichenfolge ist länger als das Original. Oder schrumpft den Puffer, wenn die neue Zeichenfolge kürzer ist.

Als Chris schrieb, wäre es viel einfacher, den Text in WM_INITDIALOG zu ändern und versuchen Sie Anforderung neu zu Satz, der sagt, dass Sie nicht SetWindowText nennen kann ().

Danke alle, ich hatte tatsächlich 24 Stunden ruhen auf dem Problem, ging dann mit einem globalen Fenster Haken WM_INITDIALOG Filterung, die eine viel einfachere Methode, war ganz gut geklappt, kein API Einhaken erforderlich, 2 Seiten Code auf nur ein paar Zeilen.

Danke für alle Antworten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top