Dynamisk Meny

Dynamisk Meny

Jeg har valgt å generere alle menyene ved runtime, da har jeg full kontroll. Tidligere fiklet jeg litt med C++Builder’s egen internasjonalisering, men den slo ikke helt an hos meg. Jeg bruker i stedet en variant av noe jeg har laget og brukt tidligere.

Der ligger alle menyteksten i en egen fil, og har du behov for oversettelse til et annet språk, sender du bare denne filen til en translatør.

Slik systemet er her nå, lastes det en DLL og ferdig med det, det er greit nok, men det skulle ikke være alt for vanskelig å skrive om dette til et antall DLL-er og angi f.eks. i en ini-fil hvilken som skal lastes.

Systemet er som følger:

Det hele starter i OnFormCreate:

void __fastcall TForm1::OnFormCreate(TObject *Sender)
{
   ---
   ---
   hLibHandle = LoadLibrary( L"DynDllProject.dll" ); // Menu strings

   if( hLibHandle )
	{

	iret = CreateDynMenu( hLibHandle );
        ---
        ---

Ikke noe hokus-pokus i denne funksjonen altså. Alle menyfunksjonene er lagt i «menu1.cpp», du vil finne den kildefilen i prosjektlisten til høyre i RAD Studio.

Hovedfunksjonen, «CreateDynMenu», burde nok kanskje vært skrevet om litt, ingen vanskelighet det heller, men jeg bruker fortsatt gamle ting som jeg vet funker og for å slippe og tenke for mye 🙂 ( Jeg har utelatt detaljer vedr. testing for oversiktens skyld)

int  __fastcall TForm1::CreateDynMenu(HINSTANCE hLibHandle)
{
         ---	
         ---
	CreateFileMenu( hLibHandle );
	CreateEditMenu( hLibHandle );
	CreateSearchMenu( hLibHandle );
	CreateImageMenu( hLibHandle );
         ---
         ---
         ---

Vi kan da gå videre til funksjonene for hver enkelt meny. De er i prinsippet helt like, omtrent som følgende fra File-menyen:

//---------------------------------------------------------------------------
// ------------------------ CreateFileMenu ----------------------------------
//---------------------------------------------------------------------------

int  __fastcall TForm1::CreateFileMenu(HINSTANCE hLibHandle)
{
	TMenuItem *ParentItem;
	TMenuItem *ParentItem2;
	TMenuItem *ChildItem;

	if( hLibHandle != 0)
	{
		charReturnFunc myFunc;

		// GetProcAddress returns a pointer to the loaded method
		myFunc = (charReturnFunc)GetProcAddress(hLibHandle, "GetFileMenuString");

		if( myFunc != 0)
		{
			ParentItem = new TMenuItem(MenuBar1);
			ParentItem->Text = myFunc(0, 256);          // 0 = "File"
			ParentItem->Name = ParentItem->Text;
			MenuBar1->AddObject(ParentItem );

			ChildItem = new TMenuItem(ParentItem);
			ChildItem->Text = myFunc(1, 256);           // 1 = "New"
			ChildItem->Name = ChildItem->Text;
			ChildItem->OnClick = menu_FILE_NEW_Click;
			ParentItem->AddObject(ChildItem);

Først må du hente opp adressen til funksjonen (det er standard bruk av en DLL) og selve menyteksten hentes opp med «ParentItem->Text = myFunc(0, 256)» hvor første parameter er nummeret til tekststringen og det andre tallet er en maks-verdi.

Komplisert? egentlig ikke, men vi er ikke ferdig ennu. Vi skal videre se på de enkelte menyfunksjoner i DLL-en her vist ved parameter 2 i «myfunc», nemlig «GetFileMenuString».

///////////////////////////////////////////////////////////////////////
//
//   wchar_t* GetFileMenuString(UINT uID, int maxlen)
//
//
wchar_t* GetFileMenuString(UINT uID, int maxlen)
{

	switch (uID) {
		case 0:
			return menu_FILE.c_str();                   // index    0
		case 1:
			return menu_FILE_NEW.c_str();               //  1
		case 2:
			return menu_FILE_OPEN.c_str();              //  2
		case 3:
			return menu_FILE_OPEN_RECENT.c_str();       //  3

OK, nå gjenstår det vel bare selve tekststringene som alle ligger i samme fil:

///////////////////////////////////////////////////////////////////////////////
//
// Lots and lots of string defs
//
// FireMonkey does not like resourcefiles, so
// this is my first solution to that problem.
//
// $Rev: 19001 $
//
// Copyright(c) 2019- Gamlisen Norway
//              All rights reserved
//
// ------------------------------------------------------------------
//  File menu textstrings
//
const String menu_FILE = _T("File");                    	// index 	0
const String menu_FILE_NEW = _T("New");                 	//          1
const String menu_FILE_OPEN = _T("Open");               	//          2
const String menu_FILE_OPEN_RECENT = _T("OpenRecent"); 		//          3
const String menu_FILE_CLOSE = _T("CloseFile");        		//          4
const String menu_FILE_CLOSE_ALL = _T("CloseAll");     		//          5
const String menu_FILE_SAVE = _T("SaveFile");          		//          6
const String menu_FILE_SAVE_AS = _T("SaveFileAs");     		//          7
const String menu_FILE_SAVE_PROJECT = _T("SaveProject"); 	//        	8
const String menu_FILE_SAVE_PROJECT_AS = _T("SaveProjectAs"); //  		9

Nå er vi ferdig med alle de enkelte delene som inngår i min form for dynamisk meny.

Komplisert?

Egentlig ikke når du først har forstått systemet 🙂 Samtlige funksjoner blir forklart i detalj på de enkelte sidene.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *

Dette nettstedet bruker Akismet for å redusere spam. Lær om hvordan dine kommentar-data prosesseres.