Click to See Complete Forum and Search --> : [RESOLVED] Need help with modify notify windowstate and sysmenu


mark103
February 14th, 2008, 11:04 AM
Hi guys

I have a question about changes the system menu and the notify texts on windowstate (like maximum, minimize and close texts on the top right corner). Is it possible to make two different classes module, E.G make one for English and make another one for French. And is it possible to call one of those class by if I selection on one of the menu item one at a time that will convert to other which it would have to be something looking like this:


http://img262.imageshack.us/img262/7185/englishbi7.jpg
http://img144.imageshack.us/img144/2592/frenchte1.jpg



Form1

Option Explicit

Private Declare Function InsertMenu Lib "user32" Alias "InsertMenuA" (ByVal hMenu As Long, ByVal nPosition As Long, ByVal wFlags As Long, ByVal wIDNewItem As Long, ByVal lpNewItem As Any) As Long
Private Declare Function GetSystemMenu Lib "user32" (ByVal hWnd As Long, ByVal bRevert As Long) As Long
Private Declare Function DrawMenuBar Lib "user32" (ByVal hWnd As Long) As Long
Private Declare Function GetMenuItemID Lib "user32" (ByVal hMenu As Long, ByVal nPos As Long) As Long
Private Declare Function SetMenuItemBitmaps Lib "user32" (ByVal hMenu As Long, ByVal nPosition As Long, ByVal wFlags As Long, ByVal hBitmapUnchecked As Long, ByVal hBitmapChecked As Long) As Long
Private Declare Function SetWindowLong& Lib "user32" Alias "SetWindowLongA" (ByVal hWnd&, ByVal nIndex&, ByVal dwNewLong&)
Private Declare Function DeleteMenu Lib "user32" (ByVal hMenu As Long, ByVal nPosition As Long, ByVal wFlags As Long) As Long

Private Const SC_CLOSE As Long = &HF060&

Private Const GWL_WNDPROC As Long = (-4&)

Private Const MF_BYCOMMAND As Long = &H0&
Private Const MF_BYPOSITION As Long = &H400&
Private Const MF_SEPARATOR As Long = &H800&
Private Const MF_CHECKED As Long = &H8&
Private Const MF_GRAYED As Long = &H1&
Private Const MF_BITMAP = &H4&



Private Sub Form_Load()
Dim hMenu As Long, hID As Long
hMenu = GetSystemMenu(Me.hWnd, 0)
'add a item in first pos
InsertMenu hMenu, &H0, MF_BYPOSITION, IDM.a, "First Menu"

'add a checked item before close item
InsertMenu hMenu, SC_CLOSE, MF_BYCOMMAND + MF_CHECKED, IDM.b, "Option &Before Close"
''add separator after close item
InsertMenu hMenu, SC_CLOSE, MF_BYCOMMAND + MF_SEPARATOR, 0&, vbNullString
''add item (after the last item)
InsertMenu hMenu, &HFFFFFFFF, 0&, IDM.c, "&New Close Button"
''add a disabled item
InsertMenu hMenu, &HFFFFFFFF, MF_GRAYED, IDM.d, "&Option MaRiO"
'add a separator

InsertMenu hMenu, &HFFFFFFFF, MF_BYCOMMAND + MF_SEPARATOR, 0&, vbNullString

InsertMenu hMenu, &HFFFFFFFF, MF_BYPOSITION, IDM.e, "&Last Option"

'refresh menu
DrawMenuBar hMenu

'draw icon in pos 13
hID& = GetMenuItemID(hMenu&, 13)
SetMenuItemBitmaps hMenu&, hID&, MF_BITMAP, Picture1.Picture, Picture1.Picture

'draw icon in first item
hID& = GetMenuItemID(hMenu&, 0)
SetMenuItemBitmaps hMenu&, hID&, MF_BITMAP, Picture2.Picture, Picture2.Picture

'delete the Close item
DeleteMenu hMenu, SC_CLOSE, MF_BYCOMMAND
'subclass

procOld = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WindowProc)

End Sub




Module1

Option Explicit

Public Enum IDM
a = 128
b
c
d
e
End Enum
Public procOld As Long
Private Declare Function CallWindowProc& Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc&, ByVal hWnd&, ByVal Msg&, ByVal wParam&, ByVal lParam&)
Private Const WM_SYSCOMMAND = &H112

Public Function WindowProc(ByVal hWnd As Long, _
ByVal iMsg As Long, ByVal wParam As Long, _
ByVal lParam As Long) As Long

Select Case iMsg
Case WM_SYSCOMMAND
Select Case wParam
Case IDM.a
MsgBox "'First menu' Cliked"
Case IDM.b
MsgBox "'Option Before Close' Cliked"
Case IDM.c
MsgBox "GoodBye"
Unload Form1
Exit Function
'Case IDM.d: MsgBox "Clik en 'Option MaRiO' Cliked" 'Disabled...
Case IDM.e
MsgBox "'Last Option' Cliked"
End Select
End Select

WindowProc = CallWindowProc(procOld, hWnd, iMsg, wParam, lParam)
End Function




Let me know if that is possible to do that?? If so how?? Also I would like to know if that is possible to call and change the notify texts on windowstate the one that come with max, mini and close button on the very top right corner of the screen??



If you know what I means, please can you post the code something would be like this:


Public Sub English_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles English.Click
Me.NotifyWindowstate.Text = "Maximum"
End Sub


Public Sub French_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles French.Click
Me.NotifyWindowstate.Text = "Maximizar"
End Sub




If not, please can you let me know what other situations that I could do that??


Let me know if that is possible....:)



Thanks,
Mark

mark103
February 14th, 2008, 07:59 PM
Is it possible to do that guys??

WoF
February 15th, 2008, 08:46 AM
Mark,
your above code comes from Vb6.0 as can be seen. I got it working in VB6 after commenting out the statements which refer to the pictureboxes I haven't got.
To make this run under VB.NET, several changes are necessary. First, all Long declarations have to be Integer, because in .NET Long is 64 and Integer is 32 bit.
Then, As Any is not allowed. Have to decide for String here, I think, because it's the menu caption passed there.
Third is the AddressOf operator. It will not convert an address to Integer and I, as a .NET novice have no solution for that. Maybe one of the .NET Aces can help here.

Changing the caption of an existing item seems possible too, but is more complicated.
Please refer to the API SetMenuItemInfo() http://allapi.mentalis.org/apilist/SetMenuItemInfo.shtml
to see a sample of how to use the MenuItemInfo structure.

How this is done in .NET, however, I couldn't figure out. Sorry.

mark103
February 15th, 2008, 09:44 AM
Thanks for your advise WoF, the code I post shows example of what I wanted the form to do by if I selection the language to french then change the system menu to french. Is it possible to do that or do I need dll to do that??




As well for notify texts on windowstate the one that come with max, mini and close button on the top right corner of the screen, is it possible to change the texts of the language??




If not, any other situations??


Thanks,
Mark

WoF
February 15th, 2008, 10:18 AM
As I sayd, you can do. Only we have to find a solution for the AddressOf operator in Vb.NET and we need to work out how change the menu item caption of an existing menu item.

The general direction is:
Create a MENUITEMINFO struct as a variable.
Call GetMenuItemInfo() API to fill the struct with data.
Change the caption
Call SetMenuItemInfo() API to set the changed data.

If I can find some time, I will make a test, but it looks bad with time this weekend, ;)

As for 'notify texts' I think you are referring to the ToolTipTexts which appear when you hover the mouse over the buttons. I must admit I have no idea how to change those...

mark103
February 15th, 2008, 02:17 PM
Ok, thanks for the info that I can get GetMenuItemInfo to call on my form. I will have to create menuinfoitem to get system menu to call but looks like it would be difficult to create one??




Let me know if you have find the better one ;)



Thanks,
Mark

WoF
February 15th, 2008, 06:26 PM
I'm just studying how subclassing is done in Vb.Net, but don't seem to get the hang of it.
I would be grateful if one of the .NET Gurus could intervene and give a short notice about that.
Obviously, it has to work somehow with the Override statement, but i don't understand how I formulate a proper override statement for the full WndProc.

After that we could think about the GetMenuItemInfo() stuff.

dglienna
February 16th, 2008, 12:33 AM
Are you talking about changing the languages while the app is running? I thought you were reading them in...

mark103
February 16th, 2008, 04:22 AM
Are you talking about changing the languages while the app is running? I thought you were reading them in...


Yeah I did, but wanted system menu to work together as well. Sorry I forgot to ask when I post language thread age ago!!!



Hope there is situation of changing system menu when I switch from english to french and switch back from french to english.




Thanks,
Mark

dglienna
February 16th, 2008, 05:01 PM
Looking good here:

http://www.astahost.com/info.php/vb-net-switch-regional-language-automatically_t6031.html

mark103
February 16th, 2008, 06:35 PM
Looking good here:

http://www.astahost.com/info.php/vb-net-switch-regional-language-automatically_t6031.html



Wrong mate, they still don't have system menu. Please read my post what I wanted, I don't want a program to write the languages, just want to exchange the language when I switch from english to french then system menu show the french language.



If I can't do that, I'll move on.


Thanks,
Mark

dglienna
February 16th, 2008, 06:54 PM
Can you read?

This tutorial sparked off from my own ventures to incorporate a particular feature in my own software - which uses mixed language (English & Thai) on a couple of screens to store user data. Certain fields, apart from First & Last Names & parts of address were to be entered in Thai. Now the current language can be easily switched by pressing Alt-Left Shift (or whatever key combination you've set your system to) - but when you consider the same key-combination has to be repeated for over 20 fields on each screen - and this times the number of records you have to enter, then is becomes a dull and humongously tedious venture. This might lead to a lot of typo's too. (In my case the users of my software had to enter over 4000 student records - soooooo... I had to do something to make the lives of those poor guys a little easier.)

:sick: :sick: :sick:

mark103
February 17th, 2008, 07:03 AM
That's only writing and store the data on the form, not changing the system menu data.



I want to change the text on my system menu data. Don't you know what system menu are??




I have downloaded the attachment from the site and nothing was on it. :mad:



Thanks,
Mark

mark103
February 18th, 2008, 08:47 AM
Please can someone help me please??

WoF
February 18th, 2008, 10:12 AM
Ok, Mark, I have worked something out, that will help you changing the caption of system menu items.

Private Declare Function GetMenuItemInfo Lib "user32" Alias "GetMenuItemInfoA" ( _
ByVal hMenu As Long, _
ByVal un As Long, ByVal b As Boolean, _
ByRef lpmii As MENUITEMINFO _
) As Long

Private Declare Function SetMenuItemInfo Lib "user32" Alias "SetMenuItemInfoA" ( _
ByVal hMenu As Long, _
ByVal uItem As Long, ByVal fByPosition As Long, _
ByRef lpmii As MENUITEMINFO _
) As Long


Private Const MIIM_TYPE = &H10

Private Type MENUITEMINFO
cbSize As Long
fMask As Long
fType As Long
fState As Long
wID As Long
hSubMenu As Long
hbmpChecked As Long
hbmpUnchecked As Long
dwItemData As Long
dwTypeData As String
cch As Long
End Type

Private Sub SysMenuChange()
Dim hMenu As Long
Dim mii As MENUITEMINFO

hMenu = GetSystemMenu(Me.hWnd, 0)

mii.cbSize = Len(mii)

If hMenu <> 0 Then
GetMenuItemInfo hMenu, 0, True, mii
mii.dwTypeData = "new caption"
mii.fMask = MIIM_TYPE
SetMenuItemInfo hMenu, 0, True, mii
End If
End Sub

To explain a little what SysMenuChange does:
GetMenuItemInfo hMenu, 0, True, mii lets the API fill the MENUITEMINFO structure with info about item 0
Then you set mii.dwTypeData to the new caption string and set mii.fMask like shown
Then SetMenuItemInfo hMenu,0,True, mii sets the new caption for item 0
Like that you can change the caption of any menuitem by number.

As for the ToolTipTexts of the other buttons I still have no idea how to do that...

WoF
February 18th, 2008, 10:18 AM
No, wait. This was again VB6 talking.
Here is the code which should work under VB.NET

Private Declare Function GetMenuItemInfo Lib "user32" Alias "GetMenuItemInfoA" ( _
ByVal hMenu As Integer, _
ByVal un As Integer, ByVal b As Boolean, _
ByRef lpmii As MENUITEMINFO _
) As Integer

Private Declare Function SetMenuItemInfo Lib "user32" Alias "SetMenuItemInfoA" ( _
ByVal hMenu As Integer, _
ByVal uItem As Integer, ByVal fByPosition As Integer, _
ByRef lpmii As MENUITEMINFO _
) As Integer


Private Const MIIM_TYPE = &H10

Private Type MENUITEMINFO
cbSize As Integer
fMask As Integer
fType As Integer
fState As Integer
wID As Integer
hSubMenu As Integer
hbmpChecked As Integer
hbmpUnchecked As Integer
dwItemData As Integer
dwTypeData As String
cch As Integer
End Type

Private Sub SysMenuChange()
Dim hMenu As Integer
Dim mii As MENUITEMINFO

hMenu = GetSystemMenu(Me.hWnd, 0)

mii.cbSize = Len(mii)

If hMenu <> 0 Then
GetMenuItemInfo hMenu, 0, True, mii
mii.dwTypeData = "new caption"
mii.fMask = MIIM_TYPE
SetMenuItemInfo hMenu, 0, True, mii
End If
End Sub

Yet I wrote the code of the previous post in VB6, where it works. I still have to test under .NET

WoF
February 18th, 2008, 10:33 AM
Ok, the code works in VB.NET.
You can integrate it in your sample program from before.
But I would take out the subclassing and would not remove the close button, as long as we have not solved this issue.
Anyway I think your problem was only to change text of existing menu items, not to add new items to the system menu.

mark103
February 19th, 2008, 03:12 PM
Thanks! Do I have to put on my windows form or just create module??





I'd much appreciate your help ;)



Thanks,
Mark

WoF
February 19th, 2008, 05:19 PM
From pure intuition I would put it in a module, keeping all API functions private to the module, exposing only a Public function which would change a SysMenu entry.
Like:
Public Sub ChangeSysMenuItem(ItemNumber as Long, NewCaption as String)

mark103
February 20th, 2008, 10:39 AM
Thanks, but there are errors code that I'm using vb6 code on .NET :confused:


Private Structure MENUITEMINFO


Error code I have receive "Structure 'MENUITEMINFO' must contain at least one instance member variable or Event declaration"



cbSize As Long
fMask As Long
fType As Long
fState As Long
wID As Long
hSubMenu As Long
hbmpChecked As Long
hbmpUnchecked As Long
dwItemData As Long
dwTypeData As String
cch As Long
End Structure


Error code I have receive "Declaration expected"


hMenu = GetSystemMenu(Me.hWnd, 0)


Error code I have receive on GetSystemMenu"Name 'GetSystemMenu' is not declared."
Error code I have receive on GetSystemMenu "Structure 'MENUITEMINFO' must contain at least one instance member variable or Event declaration"

Error code I have receive on Me.hWnd "Me' is not valid within a Module"



mii.cbSize = Len(mii)


Error code I have receive on mii.cbSize "cbSize' is not a member of 'System.Windows.Forms.MenuItem'"




Private Const MIIM_TYPE = &H10


Error code I have receive on MIIM_TYPE "Variable declaration without an 'As' clause; type of Object assumed."




mii.dwTypeData = "new caption"

Error code I have receive on mii.dwTypeData "dwTypeData' is not a member of 'System.Windows.Forms.MenuItem'."



mii.fMask = MIIM_TYPE


Error code I have receive on 'fMask' "fMask' is not a member of 'System.Windows.Forms.MenuItem"



What can we do to get those bugs to fix??



Thanks,
Mark

WoF
February 20th, 2008, 10:59 AM
Sorry I somehow copied and pasted something half ready.
Here is the complete code again. The structure must contain Dim statements as you can see, and be of integers instead of longs.
Also the missing function and constant are declared.
In case you had put that together with the other project you had, the missing declaration of GetSystemMenu() was in the form but private.
Nevertheless put the below code in a module and forget the previous post. Don't know how that happened...


Private Declare Function GetMenuItemInfo Lib "user32" Alias "GetMenuItemInfoA" ( _
ByVal hMenu As Integer, _
ByVal un As Integer, ByVal b As Boolean, _
ByRef lpmii As MENUITEMINFO _
) As Integer

Private Declare Function SetMenuItemInfo Lib "user32" Alias "SetMenuItemInfoA" ( _
ByVal hMenu As Integer, _
ByVal uItem As Integer, ByVal fByPosition As Integer, _
ByRef lpmii As MENUITEMINFO _
) As Integer

Private Declare Function GetSystemMenu Lib "user32" ( _
ByVal hWnd As Integer, ByVal bRevert As Integer _
) As Integer

Private Const MIIM_TYPE = &H10

Private Structure MENUITEMINFO
Dim cbSize As Integer
Dim fMask As Integer
Dim fType As Integer
Dim fState As Integer
Dim wID As Integer
Dim hSubMenu As Integer
Dim hbmpChecked As Integer
Dim hbmpUnchecked As Integer
Dim dwItemData As Integer
Dim dwTypeData As String
Dim cch As Integer
End Structure

Private Sub SysMenuChange()
Dim hMenu As Integer
Dim mii As New MENUITEMINFO

hMenu = GetSystemMenu(Me.Handle, 0)

mii.cbSize = Len(mii)

If hMenu <> 0 Then
GetMenuItemInfo(hMenu, 0, True, mii)
mii.dwTypeData = "new caption"
mii.fMask = MIIM_TYPE
SetMenuItemInfo(hMenu, 0, True, mii)
End If
End Sub

mark103
February 20th, 2008, 11:06 AM
Thanks, last I have receive


Private Const MIIM_TYPE = &H10


Error code I have receive on MIIM_TYPE "Variable declaration without an 'As' clause; type of Object assumed."





What can I do to ignore those error??



Thanks,
Mark

dglienna
February 20th, 2008, 11:19 AM
If you would have typed it, you get AS automatically

Private Const MIIM_TYPE As Long = &H10


and a Hex number is a Long in this case

mark103
February 20th, 2008, 12:00 PM
Ah, thanks for your advise! I have forgot to put As Long next to MIIM_TYPE which I have put As Object where I nearly got myself correct. Your advise have make me a better experience to learn more ;)






At least, I would like to know how to call a module in vb.net?



Thanks,
Mark

dglienna
February 20th, 2008, 12:37 PM
Your subroutines and functions are now defined when you try to use them. You don't call a module.

mark103
February 20th, 2008, 01:25 PM
Ok, so how do I call API function from my menu item??




Sorry I am new on this and hope I will learn from this in the near future ;)




Thanks,
Mark

dglienna
February 20th, 2008, 01:40 PM
Now you can use the API's that are defined GetSystemMenu() is one, right? Now it should be ok to use. Check for it to see.

mark103
February 20th, 2008, 01:46 PM
Now you can use the API's that are defined GetSystemMenu() is one, right? Now it should be ok to use. Check for it to see.



Yeah, i am asking what is the code to call API??



Hopefully it will works! :thumb:



Thanks,
Mark

dglienna
February 20th, 2008, 07:41 PM
You had it:

hMenu = GetSystemMenu(Me.hWnd, 0)

mark103
February 20th, 2008, 08:49 PM
Thanks, sorry I didn't know the code was API call.



Public Sub test_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles test_Click
hMenu = GetSystemMenuInfo(Me.hWnd, 0)



I have receive another error code on hMenu:: "Name 'GetSystemMenuInfo' is not declared"
I have receive another error code on GetSystemMenuInfo: "Name 'hMenu' is not declared"



Why do I have to receive those errors?? :(


Thanks,
Mark

WoF
February 21st, 2008, 11:05 AM
The crux lies in the scope where you declare a function.
If you want API calls available throughout everywhere in your program, you put the declaration in a module and make it a
Public Function WahateverAPICall(...)
Now it is known Public to all modules and forms of your program.
The last code I gave you has the functions declared Private, so they are only known within the module or form where they are.

For your purpose I'd best put all API and related Constant declarations in one module and use Public instead of Private, so as you have all the related names known everywhere in your program.

The second error of hMenu you get, because you don't dim a variable of this name before attempting to use it. You should know this already, don't you?

dim hMenu as Integer
hMenu = GetSystemMenuInfo(Me.hWnd, 0)

mark103
February 21st, 2008, 07:01 PM
Thanks! I have copied your code but I'm afraid to say I am having the same trouble as I had. I don't know why or where the errors are coming from, hopefully you can take a look on the following attachment I have included which it would be easier for you to take a look because you may have the better knowedge than I do. :)




I did my best to find any other situations to get API call with properly call name but everything seen to be failed or messed.




Hope you guys can help me out to find out what went wrong and why the errors code I have received which the API call didn't works in the properly way.


Thanks,
Mark

WoF
February 22nd, 2008, 10:26 AM
Mark, you did not do everything I told you, that's why you still get these errors with the GetSystemMenu.
Go to the Module3 you have created beautyfully.
And there find every word which spells 'Private' and change it to 'Public'.

I explained at length about the meaning of those keywords for the scope of a function. When it is declared Private, it is only known within the Module where it is. If you want to call it from outside, say from Form1 you declare it 'Public' so it is known everywhere in your project, ok?

The second error with hWnd is easy to come by:
Change the expression Me.hWnd to Me.Handle
I missed that: the hWnd of VB6 is now called Handle in .NET

Because these are some mere changes of text I think you can perform the corrections by yourself:
A few changes from Private to Public in Module3
1 Change of hMenu = GetSystemMenuInfo(Me.hWnd, 0) in Form1 LANG_French_Click() where you change Me.hWnd to Me.Handle

Only another advice, because I'm already afraid to spot where this is going to. You will add the code to the French_Click, and then you will add the same code again to the English_Click. Please, reflect and remember what I told you before about programming: You write one routine which does it for ALL languages and call it from a dozen of other click events.
Look at the code we had so far. Everywhere a text of a certain language is loaded, only ONE routine does the job and takes the text from the file which is named in the Public variable INIFile. You don't need to write the very same code over and over again.

mark103
February 22nd, 2008, 03:04 PM
Thanks, I have rename the codes the one you gave me. But 'GetSystemMenuInfo' did not solve it. I have receive the same error "Name 'GetSystemMenuInfo' is not declared"




Do you know why and what did I need to do to get it to solve??


Thanks,
Mark

WoF
February 22nd, 2008, 05:30 PM
Ok. Post the sample as it is again.
I'm sure it's some simple and stupid mistake.
Have you checked if the function GetSystemMenuInfo IS DECLARED PUBLIC?

mark103
February 22nd, 2008, 07:00 PM
Ok, here it the sample file.





I'd appreciate the help you have done and I do not blame on anyone who make mistake as it can happens sometimes like I make mistakes so don't worry about it :thumb:




Yes I did checked all the function of GetSystemMenuInfo which they're declared public.



Hopefully you can recover why GetSystemMenuInfo cause the error.



Thanks,
Mark

WoF
February 22nd, 2008, 07:43 PM
Ok. You'll have to wait until tomorrow, though.
I've only Visual Studio 2003 here at home and it won't read the project for some reason. I will check it tomorrow in the office, ok?

mark103
February 22nd, 2008, 08:27 PM
Yeah, that's fine. Hopefully you can be able to sort it out by tomorrow.





I'm looking forward once again. :thumb:



Thanks,
Mark

WoF
February 23rd, 2008, 06:09 AM
Well, now that was easy:
The name is GetSystemMenu, not GetSystemMenuInfo.
So in Form1 you write: hMenu = GetSystemMenu(Me.Handle, 0)

Again, let me advise you:
Don't continue writing code in the LANG_French_Click() event handler. That's silly.
Look, you shall keep the event handler as simple as possible.
What it does:
1. Select the language by setting which ini file is to be used further on
2. calling ReadLanguagesUnicode() which should do ALL of the settings, ok?

What you do (or should do, I cannot predict what you actually will do :rolleyes: ):
Go to the Module2. It contains all procedures for setting menu items and everything.
Start writing a new sub named
Public Sub ReadSystemMenuItems()
There we gonna put the code to read the system menu items from the current ini file. The code is the SAME for english and french, understand?
To run this routine we set a call at the very end of ReadLanguagesUnicode, right before its End Sub, like
Call ReadSystemMenuItems
So NO additional code is to go to the event handlers, right?
Did you get what I'm trying to explain?

mark103
February 23rd, 2008, 06:51 PM
Ok, I have changed the code what you suggestion me to do so do I have to copy all of the code from ReadLanguagesUnicode and put on Public Sub ReadSystemMenuItems() function??




I have writing the code Call ReadSystemMenuItems in my LANG_French_Click() to read system menu but nothing are displaying or working. I hope that we can get system menu to start reading the language by if I select the menu item language, E.G french. Then system menu attempt to read the text from module3.



Hopefully we can get this to work and get through.


Thanks,
Mark

WoF
February 24th, 2008, 08:53 AM
No, no, no. You seem to have misunderstood fully.
You leave all the code as it was.
To keep the overview we write a new function in Module2
Public Sub ReadSystemMenuItems()
Therein we will write all the code necessary to read the system menu items from the current language ini file.
To run the code, we put a Call ReadSystemMenuItems as a last statement into the ReadLanguagesUnicode() procedure (which we don't change in any other respect, because it works good).

Therefore you dont have to put ANY new code into your Click events, which is what we want to achieve. NO additional code to the event handlers.

Have you understood the concept?

If not, tell me, then I will prepare the last version you sent so as to my proposals.

mark103
February 24th, 2008, 10:30 AM
Sorry, but that what you have told me to put Public Sub ReadSystemMenuItems() on module 2. So i did it, here it the code:



Imports System.IO

Module Module2
Public Language As String
Public IniFile As String
'this should hold
Public UniCodeFile As String

Public Sub ReadSystemMenuItems()

End Sub
Function ReadCompleteFile() As Boolean
Dim sr As New StreamReader(IniFile)
If sr Is Nothing Then
MsgBox("File " + IniFile + " file not found", MsgBoxStyle.Exclamation Or MsgBoxStyle.OkOnly, "Languge file not found!")
Exit Function
End If
UniCodeFile = sr.ReadToEnd
sr.Close()
ReadCompleteFile = True

End Function

Function GetFromFile(ByVal SectionName As String, ByVal ValueName As String, ByVal DefaultVal As String) As String
Dim sp As Integer 'section position
Dim se As Integer 'string end
Dim vp As Integer 'value position
Dim sec As String 'entire section
Dim vst As String
'
GetFromFile = DefaultVal
sp = InStr(UniCodeFile, "[" + SectionName + "]")
If sp = 0 Then Exit Function Else sec = Mid$(UniCodeFile, sp + Len(SectionName) + 2)
se = InStr(sec, "[")
If se Then sec = Left$(sec, se - 3)
'
vp = InStr(sec, vbCrLf + ValueName + "=")
If vp = 0 Then Exit Function Else vst = Mid$(sec, vp + 2)
se = InStr(vst, vbCrLf)
If se Then vst = Left$(vst, se - 1)
'
GetFromFile = Mid$(vst, InStr(vst, "=") + 1)

End Function

Sub ReadLanguagesUnicode()
If Not ReadCompleteFile() Then Exit Sub
Language = GetFromFile("ControlsLanguage", "Language", "")
Form1.Text = GetFromFile("ControlsLanguage", "Title", "")
Form1.LANG_English.Checked = (Language = "English")
Form1.LANG_French.Checked = (Language = "French")


Dim mi As MenuItem
For Each mi In Form1.MainMenu1.MenuItems
ReadUnicodeMenuItems(mi)
Next

' next section is for other controls, beginning with alternate ToolStripMenu
' but also usable with other types of controls

Dim ctl As Control
Dim ms As New MenuStrip
Dim ts As MenuStrip
Dim ti As ToolStripItem


For Each ctl In Form1.Controls
If ctl.GetType Is ms.GetType Then
ts = ctl
For Each ti In ts.Items
ReadUnicodeToolItems(ti)
Debug.Print(ti.Name)
ReadItems(ti)
Next
End If
Next
End Sub

Private Sub ReadUnicodeMenuItems(ByRef MItem As MenuItem)
Dim mi As MenuItem
If MItem.Tag <> "" Then MItem.Text = GetFromFile("ControlsLanguage", MItem.Tag, MItem.Text)
For Each mi In MItem.MenuItems
ReadUnicodeMenuItems(mi)
Next
End Sub

Private Sub ReadUnicodeToolItems(ByRef TItem As ToolStripMenuItem)
Dim sep As New ToolStripSeparator
TItem.Text = GetFromFile("ControlsLanguage", TItem.Name, "")
For Each Child As Object In TItem.DropDownItems
If Not Child.GetType Is sep.GetType Then ReadUnicodeToolItems(Child)
Next
End Sub

Private Sub ReadItems(ByVal Parent As ToolStripMenuItem)
Dim sep As New ToolStripSeparator

Parent.Text = ReadIniFile(IniFile, "ControlsLanguage", Parent.Name, "")
For Each Child As Object In Parent.DropDownItems
If Not Child.GetType Is sep.GetType Then ReadItems(Child)
Next
End Sub



There are some confusion what you have asked me to do so yes I do understood the concept.



Hopefully we can get this resolve :)



Thanks,
Mark

dglienna
February 24th, 2008, 10:15 PM
So it works right? Why don't you post the latest code before he asks.

WoF
February 25th, 2008, 08:48 AM
The above start looks good. Thats what I suggested.
My fearful Nonono was in response to your question
do I have to copy all of the code from ReadLanguagesUnicode and put on Public Sub ReadSystemMenuItems() function?

Ok. Now we can start write the ReadSystemMenuItems() code

And to get the function called we put the call as a last statement into ReadLanguagesUnicode()


Sub ReadLanguagesUnicode()
....
'all of the previously established code stays here and just before the end we call
ReadSystemMenuItems
End Sub

In fact we do not even need the Call statement. Just writing down the name of the sub will call it there.

That is the frame for our work. Now we can think about implementing the Item reading.
Ok, so far?

WoF
February 25th, 2008, 08:53 AM
As an aftetrthought, it was more elegant If you'd put the

Public Sub ReadSystemMenuItems()

End Sub

at the end of the module, right after the last sub.
The logical structure of module 2 is in better order then, see?
First come the main procedure, followed by all the ReadItem-procedures which are called by the main procedure.

mark103
February 28th, 2008, 09:04 PM
Thanks, it's ok so far I have put the code ReadSystemMenuItems on line at the end of sub ReadLanguagesUnicode statement. I have also placed Public Sub ReadSystemMenuItems() at the end of module2 statement also with Call ReadSystemMenuItems() but suddely, I have receive the error:



StackOverflowExeption was unhandled

An unhandled exception of type 'System.StackOverflowException' occurred in Project1.exe



what's wrong?? I thought everything was almost done? :confused:



Mark

WoF
February 29th, 2008, 07:02 AM
It seems you have put a call to itself IN itself. Looks like you have written:

Public Sub ReadSystemMenuItems
Call ReadSystemMenuItems
End Sub

This will call itself endlessly and overflow the stack.
This call has nothing to do there. I didn't mean you to put it there. :)
If you are in doubt what you did, append the Module2.vb for me to see.

I was already thinking of how to implement your code, then, when I noticed that you have taken out the [OPTIONS] section and changed the ini file convention. Why did you do that? But no matter, we can put up with it.

Since the system menu has the items
Restore, Move, Size, Minimize, Maximize and Close
and is always the same, we could create a section like that:
code]
[SystemMenu]
1=Restore
2=Move
3=Size
4=Minimize
5=Maximize
7=Close
[/code]
The #6 item is the separator and wo don't change it.
In the french file you the have to put the apropriate french words.

If you agree with this structure, we can write the code for ReadSystemMenuItems().

mark103
February 29th, 2008, 10:36 AM
Ok, here it the module2 code:



Option Explicit On

Imports System.IO

Module Module2
Public Language As String
Public IniFile As String
'this should hold
Public UniCodeFile As String

Function ReadCompleteFile() As Boolean
Dim sr As New StreamReader(IniFile)
If sr Is Nothing Then
MsgBox("File " + IniFile + " file not found", MsgBoxStyle.Exclamation Or MsgBoxStyle.OkOnly, "Languge file not found!")
Exit Function
End If
UniCodeFile = sr.ReadToEnd
sr.Close()
ReadCompleteFile = True

End Function

Function GetFromFile(ByVal SectionName As String, ByVal ValueName As String, ByVal DefaultVal As String) As String
Dim sp As Integer 'section position
Dim se As Integer 'string end
Dim vp As Integer 'value position
Dim sec As String 'entire section
Dim vst As String
'
GetFromFile = DefaultVal
sp = InStr(UniCodeFile, "[" + SectionName + "]")
If sp = 0 Then Exit Function Else sec = Mid$(UniCodeFile, sp + Len(SectionName) + 2)
se = InStr(sec, "[")
If se Then sec = Left$(sec, se - 3)
'
vp = InStr(sec, vbCrLf + ValueName + "=")
If vp = 0 Then Exit Function Else vst = Mid$(sec, vp + 2)
se = InStr(vst, vbCrLf)
If se Then vst = Left$(vst, se - 1)
'
GetFromFile = Mid$(vst, InStr(vst, "=") + 1)

End Function

Sub ReadLanguagesUnicode()
If Not ReadCompleteFile() Then Exit Sub


Dim mi As MenuItem
For Each mi In Form2.MainMenu1.MenuItems
ReadUnicodeMenuItems(mi)
Next

' next section is for other controls, beginning with alternate ToolStripMenu
' but also usable with other types of controls

Dim ctl As Control
Dim ms As New MenuStrip
Dim ts As MenuStrip
Dim ti As ToolStripItem


For Each ctl In Form2.Controls
If ctl.GetType Is ms.GetType Then
ts = ctl
For Each ti In ts.Items
ReadUnicodeToolItems(ti)
Debug.Print(ti.Name)
ReadItems(ti)
ReadSystemMenuItems()
Next
End If
Next
End Sub

Private Sub ReadUnicodeMenuItems(ByRef MItem As MenuItem)
Dim mi As MenuItem
If MItem.Tag <> "" Then MItem.Text = GetFromFile("ControlsLanguage", MItem.Tag, MItem.Text)
For Each mi In MItem.MenuItems
ReadUnicodeMenuItems(mi)
Next
End Sub

Private Sub ReadUnicodeToolItems(ByRef TItem As ToolStripMenuItem)
Dim sep As New ToolStripSeparator
TItem.Text = GetFromFile("ControlsLanguage", TItem.Name, "")
For Each Child As Object In TItem.DropDownItems
If Not Child.GetType Is sep.GetType Then ReadUnicodeToolItems(Child)
Next
End Sub

Private Sub ReadItems(ByVal Parent As ToolStripMenuItem)
Dim sep As New ToolStripSeparator

Parent.Text = ReadIniFile(IniFile, "ControlsLanguage", Parent.Name, "")
For Each Child As Object In Parent.DropDownItems
If Not Child.GetType Is sep.GetType Then ReadItems(Child)
Next
End Sub
Public Sub ReadSystemMenuItems()
Call ReadSystemMenuItems()
End Sub
End Module



You could write the code which I would be happy to agree with this structure :)



Hopefully after that, I can start to call ReadSystemMenuItems.

Thanks,
Mark

WoF
February 29th, 2008, 05:16 PM
Ok, here it the module2 code:

Public Sub ReadSystemMenuItems()
Call ReadSystemMenuItems()
End Sub
End Module



Look. :) It's exactly like I predicted. You call the same procedure from within itself. That MUST produce an error.

Ok. As you agree with the structure I put forward, I will work out a code to put in our new Sub. :)
Only I will do so tomorrow, I'm simply too tired tonight.

See you. ;)

WoF
March 7th, 2008, 08:00 AM
Hello Mark.
I have made an effort to put the system menu under control.
I better send the complete project.
Look into the .ini files. I only have dummy item names because I cant remember the proper french expressions.
It looks like:
[SystemMenu]
0=Restore
1=Move
... and so on
There is no 5 because this is the seperator and will produce an error when trying to change.

Also despite my own proposal I have put the ReadSystemMenuItems() into module3 because all the definitions for the system menu are already there.

Only thing I have not found out: when changing the item texts, the icons on the left side seem to get lost. Still have to do a little research there.

mark103
March 8th, 2008, 06:14 AM
Thanks, this is awesome :D Hopefully we can find a way how to place the icon next to the text. Can you help if I can change the font type of bold to Regular text style??





Hopefully I can make the look better ;)



Thanks,
Mark

WoF
March 8th, 2008, 04:56 PM
I would try out the SetMenuItemBitmaps() on monday. Haven't VB2005 here for the weekend.

Have you got an icon you want to use?

WoF
March 10th, 2008, 10:54 AM
Mark,
a little more research has revealed a solution which makes SetMenuItemBitmaps() obsolete.
It was a mistake in using the MENUITEMINFO.fMask value which killed away the icons and the fontbold.
I have attached a new Module3.vb code which leaves font and icon untouched when changing the text.

Another thing:
In Module2, in Function ReadCompleteFile you better put an On Error Resume Next as very first Line, like:

Function ReadCompleteFile() As Boolean
On Error Resume Next
Dim sr As New StreamReader(IniFile)
....

Otherwise you get an error when changing the folder or folder name of the project.
The On Error Resume Next lets you step into the error handler instead and assume the default language to english. This only ever can happen the first time the program is run from a different folder, but it CAN happen. So this prevents the program from crashing then.

mark103
March 11th, 2008, 04:33 PM
Thanks for your help WoF! This is awesome and I'd love this work you have given me. But hey, I wondering how I could change the font style, E.G change the style for 'Close' and 'Restore' which I would like to change from Bold to Regular. How I can do that, what's the proper way to do??




Thanks for the help, you have been awesome :D



Thanks,
Mark

WoF
March 12th, 2008, 12:28 PM
Thanks for the flowers. :)

I haven't yet researched to a deeper extend, but there exists an API call ModifyMenu. If I find time tonight I shall take a look how it could be accomplished to change an item's font. Should be possible but I don't know many details about menu structures. I would have expected the font to be specified in the MENUITEMINFO struct, but it isn't...

I see what I can find out.

mark103
March 13th, 2008, 04:31 PM
No problem WoF :)



Let me know when you have found situations.



It would be useful when someone see this and then post.


Thanks,
Mark

WoF
March 19th, 2008, 09:06 AM
I reply here to your PM, where we have resolved the MenuItem changing meanwhile.

I can't experience your problem with menu size changing at my place.
I'm attaching 2 images to show the french and english system menus.
The sizes are still the same even after me changing 20 times from french to english.

There is no choice as to attach the project again, cause mine seems to be different then. :)

dglienna
March 19th, 2008, 10:52 PM
Seems like you're doing things the hard way. Look at this thread:

http://www.codeguru.com/forum/showthread.php?p=1698503#post1698503

mark103
March 20th, 2008, 11:14 AM
Thanks for your advise my dear friends WoF and dglienna. Following on dglienna's earlier post on my previous thread, I did not awake that resource file is actually the better place for me to use with more support on it. I found the code which it would be much useful to get access to the resource:



Imports System.Globalization
Imports System.ComponentModel
Imports System.Resources
Imports System.Threading

Private Sub Text1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Text1.Click
Me.Text1.Text = (My.Resources.RuntimeStrings_fr.text1)
End Sub


Private Function MenuItems(ByVal locale_name As String, ByVal checked_button As ToolStripMenuItem, ByVal unchecked_button As ToolStripMenuItem) As Frm1
If Not Me.Created Then Return Nothing

' Make a CultureInfo.
Dim culture_info As New CultureInfo(locale_name)

' Make the thread use this locale.
Thread.CurrentThread.CurrentUICulture = culture_info
Thread.CurrentThread.CurrentCulture = culture_info

Dim frm As New Frm1
frm.Location = Me.Location
Return frm
End Function



How do I write on Private Function to grab the system menu info and replace the texts that come on resource file??



It bit the same as the old work on my project that WoF have already post it. So sorry about changing it again but I didn't realised it what I want.




Thanks,
Mark

mark103
March 20th, 2008, 11:41 AM
Found the proper code as it works but how I could read each of different system menu items, E.G Restore, Move Size, Minimize, Maximum and Close.

The working code is:
a = (My.Resources.RuntimeStrings_en1.English)



The code on above shows that it grab the system menu items and display the info from the resource to replace all of the system menu items texts.




What way I could grab each of those system menu items from grab the info on resource and replace the texts instead??



Something would be like this:


a = MenuItems1(My.Resources.RuntimeStrings_en1.English)
a = MenuItems2(My.Resources.RuntimeStrings_en1.English)
a = MenuItems3(My.Resources.RuntimeStrings_en1.English)
a = MenuItems4(My.Resources.RuntimeStrings_en1.English)
a = MenuItems5(My.Resources.RuntimeStrings_en1.English)
a = MenuItems6(My.Resources.RuntimeStrings_en1.English)




Hope you guys can help me with this and it will be resolve :)



Thanks,
Mark

mark103
April 24th, 2008, 08:00 PM
Any luck yet if the system menu can be possibly to change the font which also to support unicode character sets??




Thanks,
Mark

dglienna
April 24th, 2008, 08:11 PM
You have never helped anyone with anything. In 3 years, you should be able to help someone, don't you think?

You said before that you 'found the code' that solved your problem. That is not what programming is!

If you are waiting for someone ELSE to post the same question to get it answered, then I guess the answer is NO.

I don't have any reason to do it, though.

mark103
May 7th, 2008, 05:37 PM
is it possible to change the font for system menu??



Any info to post will be welcome :)



Thanks,
Mark

dglienna
May 7th, 2008, 05:45 PM
www.rentacoder.com maybe?