Some time ago in the study of a game assist, the foreigner produced, support seven languages, but this auxiliary related plug-in is rarely Chinese, because the author are foreigners, and they do not want to add Chinese. There are some non-encrypted plug-in is good domestic users of the use of tools and software manual Chinese, but after the confusing encryption of the plug-in is more difficult, one needs to decrypt, the second is the number of plug-ins updated quickly, finally made to give up. One day, a user asked me, can do a patch, not to decrypt and not to modify the source program, just in the window display when the text of the Chinese, he means the hook form display process, obviously, this is a very good idea.
Many years ago, has been popular with a name "NJStar" software, and then a "fast translation of Jinshan", these two can be the program interface to localize the plug, and I want to do is the patch, that is, inside the hanging, although the form is different, but the principle is always the same bar. With this idea, I started a new code trip, but it didn't take long for me to give up completely, mainly because the Windows window is supported only, not for WPF, because the content in the WPF form is not a valid control and is more difficult to "automate".
I've sold enough of my xiaoguanzi, you know, and in the end, I've achieved my goal.
. NET programs are only as flexible as fishing in the. NET environment. For normal WinForm and WPF forms, after the window constructor is run, we only need to traverse all the private fields of the window class to get all the controls, directly modify their corresponding text, this is the whole process of Chinese! So here's the question, how to get the instance reference for the window, how to modify the text before the window is displayed, and how to handle the user-defined form controls. Here's the answer.
First of all, the second problem is achieved through the improper means of methodreplace, the principle is to modify the code address in the CLR method MethodDesc, the method of calling the source method has not been JIT before the new method address to replace the source method, The entire method body is shifted to the new method when the source method is called (please Google for the procedure). Because the method that displays the window is made up of. NET provides out-of-the-box compiled native code, is unable to replace the address, so the best pointcut is the window's constructor. With the Assemblyload event of the current domain, it is easy to take control when the assembly is loaded, then traverse through all the window classes in the assembly, and then address the changes to their constructors, so that they are robbed before the method of creating the window is JIT. Consider that all the controls in the window need to be created in the constructor, usually by calling a method named InitializeComponent, but this method name is not reliable because it is confused, So you still have to use the Opcodes.calli field in the new method to invoke the source address of the construction method with the correct signature (see MSDN for details) to complete the initialization of the internal controls of the form, so that the problem is resolved and the modification can be traversed directly. And so on, how to modify the content is not comprehensive, there are omissions. Okay, I forgot. Some lists are initialized when the window is first displayed, which is caused by the IDE of VS, and everyone likes to put user-initialized data in the window's Load event. How to respond? Very simply, I have added the process of Chinese to the load event, so that the process of the Chinese will occur after the window original Load event.
When the second problem is solved perfectly, the first problem is solved, the constructor of the window is an instance method, the first parameter of the instance method is always this, so the addition of events, the reflection modification private fields are implemented, but also can achieve more localization things ...
The third problem is relatively simple, but only a lot of complexity. We know that most of the text in the near piece is placed in a property named text, which can be modified directly or reflected, but there are still a few controls that require special handling, such as the Caption property of the ToolTip control, the hierarchy of the menu, the Content collection in the list near the item, The name of the attribute in the PropertyGrid. Again, there are some custom style of the window class, the text of their control may be placed in the name of text, Title, SubTitle, Caption, Value1, Value2 and so on attributes, using reflection traversal query on it, of course, also for these types and fields cache, This will increase efficiency.
Later, although the function is realized, but it is not easy to use, the user experience is very poor, mainly the effect of automatic translation is very unsatisfactory, but I really can not solve this complex professional problems, so decisively give up automatic translation, to the output list, and then the purpose of translation.
Localizing a running. NET window in the CLR