Using an Input Method Editor in a Game

Unity动态逻辑编程:表达式树实现游戏运行时逻辑配置 表达式树是.NET中一种将代码逻辑表示为树形数据结构的技术,其核心原理是将运算、方法调用等操作抽象为节点,通过组合这些节点动态构建可执行逻辑。这项技术的价值在于实现了逻辑与代码的解耦,允许在运行时动态修改和配置程序行为,从而极大提升了系统的灵活性和可维护性。在游戏开发领域,这一特性尤其适用于需要频繁调整数值公式、事件条件与AI行为的场景。通过将游戏逻辑(如伤害计算、任务条件)转化为可配置的表达式树,开发者能够构建出支持策划直接调整的动态系统,实现高效的迭代与协作。本文以Unity中的动态伤害计算系统为例,详 阅读详情

Using an Input Method Editor in a Game

By Jack Lin, Software Design Engineer

Microsoft Corporation

December 2004

Introduction

An Input Method Editor (IME) is a program that allows easy text entry using a standard keyboard for East Asian languages such as Chinese, Japanese, Korean, and other languages with complex characters. For example, with IMEs a user can type complex characters in a word processor, or a player of a massive multiplayer online game can chat with friends in complex characters.

This topic explains how you can implement a basic IME edit control in a full-screen Microsoft DirectX application. Applications that take advantage of DXUT automatically get IME functionality. For applications that do not make use of the framework, this topic describes how to add IME support to an edit control.

Contents:

Default IME Behavior

IMEs map keyboard input to phonetic components or other language elements specific to a selected language. In a typical scenario, the user types keys that represent pronunciation of a complex character. If the IME recognizes the pronunciation as valid, it presents the user with a list of word or phrase candidates from which the user can select a final choice. The chosen word is then sent to the application through a series of Microsoft Windows WM_CHAR messages. Because the IME works at a level below the application by intercepting keyboard input, the presence of an IME is transparent to the application. Almost all Windows applications can readily take advantage of IMEs without being aware of their existence and without requiring special coding.

A typical IME displays several windows to guide the user through character entry, as shown in the following examples.

IME character entry display windows

Window TypeDescriptionIME Output
A. Reading WindowContains keystrokes from the keyboard; typically changes after each keystroke.reading string
B. Composition WindowContains the collection of characters that the user has composed with the IME. These characters are drawn by the IME on top of the application. When the user notifies the IME that the composition string is satisfactory, the IME then sends the composition string to the application via a series of WM_CHAR messages.composition string
C. Candidate WindowWhen the user has entered a valid pronunciation, the IME displays a list of candidate characters that all match the given pronunciation. The user then selects the intended character from this list, and the IME adds this character to the Composition Window display.the next character in the composition string
D. Input Locale indicatorShows the language the user has selected for keyboard input. This indicator is embedded in the Windows taskbar. The input language can be selected by opening the Regional and Language Options Control Panel and then clicking Details on the Languages tab.-

Using IMEs with DXUT

In DXUT, the CDXUTIMEEditBox class implements IME functionality. This class is derived from the CDXUTEditBox class, the basic edit control provided by the framework. CDXUTIMEEditBox extends that edit control to support IMEs by overriding the CDXUTIMEEditBox methods. The classes are designed this way to help developers learn what they need to take from the framework to implement IME support in their own edit controls. The rest of this topic explains how the framework, and CDXUTIMEEditBox in particular, overrides a basic edit control to implement IME functionality.

Most of the IME-specific variables in CDXUTIMEEditBox are declared as static, because many IME buffers and states are specific to the process. For instance, a process has only one buffer for the composition string. Even if the process has ten edit controls, they will all be sharing the same composition string buffer. The composition string buffer for CDXUTIMEEditBox is therefore static, preventing the application from taking up unnecessary memory space.

CDXUTIMEEditBox is implemented in the following DXUT code:

(SDK root)/Samples/C++/Common/DXUTgui.cpp

Overriding the Default IME Behavior

Normally an IME uses standard Windows procedures to create a window (see Using Windows). Under normal circumstances, this produces satisfactory results. However, when the application presents in full-screen mode, as is common for games, standard windows no longer work and may not display on top of the application. To overcome this issue, the application must draw the IME windows itself instead of relying on Windows to perform this task.

When the default IME window creation behavior does not provide what an application requires, the application can override the IME window handling. An application can achieve this by processing IME-related messages and calling the Input Method Manager (IMM) API. See Input Method Editor.

When a user interacts with an IME to input complex characters, the IMM sends messages to the application to notify it of important events, such as starting a composition or showing the candidate window. An application typically ignores these messages and passes them to the default message handler, which causes the IME to handle them. When the application, instead of the default handler, handles the messages, it controls exactly what happens at each of the IME events. Often the message handler retrieves the content of the various IME windows by calling the IMM API. Once the application has this information, it can properly draw the IME windows itself when it needs to render to the display.

Functions

An IME needs to get the reading string, hide the reading window, and get the orientation of reading window. This table shows the the functionalities per IME version:

 Getting reading stringHiding reading windowOrientation of reading window
Before version 6.0Access IME private data directly. See "4 Structure"Trap IME private messages. See "3 Messages"Examine registry information. See "5 Registry Information"
After version 6.0GetReadingStringShowReadingWindowGetReadingString

Messages

The following messages don't have to be processed for newer IME that implements ShowReadingWindow().

The following messages are trapped by application message handler (i.e. they are not passed to DefWindowProc) to prevent the reading window from showing up.

Msg == WM_IME_NOTIFY
wParam == IMN_PRIVATE
lParam == 1, 2 (CHT IME version 4.2, 4.3 and 4.4 / CHS IME 4.1 and 4.2)
lParam == 16, 17, 26, 27, 28 (CHT IME version 5.0, 5.1, 5.2 / CHS IME 5.3)

Examples

The following examples illustrate how to get reading string information from older IME that doesn't have GetReadingString(). The code generates the following outputs:

DWORD dwlenLength of the reading string
DWORD dwerrIndex of error char
LPWSTR wstrPointer to the reading string
BOOL unicodeIf true, the reading string is in Unicode format. Otherwise it's in multibyte format.

CHT IME version 4.2, 4.3 and 4.4

LPINPUTCONTEXT lpIMC = _ImmLockIMC(himc);
LPBYTE p = *(LPBYTE *)((LPBYTE)_ImmLockIMCC(lpIMC->hPrivate) + 24);
if (!p) break;
dwlen = *(DWORD *)(p + 7*4 + 32*4);
dwerr = *(DWORD *)(p + 8*4 + 32*4);
wstr = (WCHAR *)(p + 56);
unicode = TRUE;

CHT IME version 5.0

LPINPUTCONTEXT lpIMC = _ImmLockIMC(himc);
LPBYTE p = *(LPBYTE *)((LPBYTE)_ImmLockIMCC(lpIMC->hPrivate) + 3*4);
if (!p) break;
p = *(LPBYTE *)((LPBYTE)p + 1*4 + 5*4 + 4*2 );
if (!p) break;
dwlen = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16);
dwerr = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16 + 1*4);
wstr = (WCHAR *)(p + 1*4 + (16*2+2*4) + 5*4);
unicode = FALSE;

CHT IME version 5.1, 5.2 and CHS IME version 5.3

LPINPUTCONTEXT lpIMC = _ImmLockIMC(himc);
LPBYTE p = *(LPBYTE *)((LPBYTE)_ImmLockIMCC(lpIMC->hPrivate) + 4);
if (!p) break;
p = *(LPBYTE *)((LPBYTE)p + 1*4 + 5*4); 
if (!p) break;
dwlen = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16 * 2);
dwerr = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16 * 2 + 1*4);
wstr  = (WCHAR *) (p + 1*4 + (16*2+2*4) + 5*4);
unicode = TRUE;

CHS IME version 4.1

// GetImeId(1) returns VS_FIXEDFILEINFO:: dwProductVersionLS of IME file
int offset = ( GetImeId( 1 ) >= 0x00000002 ) ? 8 : 7;
LPINPUTCONTEXT lpIMC = _ImmLockIMC(himc);
BYTE p = *(LPBYTE *)((LPBYTE)_ImmLockIMCC(lpIMC->hPrivate) + offset * 4);
if (!p) break;
dwlen = *(DWORD *)(p + 7*4 + 16*2*4);
dwerr = *(DWORD *)(p + 8*4 + 16*2*4);
dwerr = min(dwerr, dwlen);
wstr = (WCHAR *)(p + 6*4 + 16*2*1);
unicode = TRUE;

CHS IME version 4.2

int nTcharSize = IsNT() ? sizeof(WCHAR) : sizeof(char);
LPINPUTCONTEXT lpIMC = _ImmLockIMC(himc);
BYTE p = *(LPBYTE *)((LPBYTE)_ImmLockIMCC(lpIMC->hPrivate) + 1*4 + 1*4 + 6*4);
if (!p) break;
dwlen = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16 * nTcharSize);
dwerr = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16 * nTcharSize + 1*4);
wstr  = (WCHAR *) (p + 1*4 + (16*2+2*4) + 5*4);
unicode = IsNT() ? TRUE : FALSE;

IME Messages

A full-screen application must properly handle the following IME-related messages:

WM_INPUTLANGCHANGE

The IMM sends a WM_INPUTLANGCHANGE message to the active window of an application after the input locale has been changed by the user with a key combination (usually ALT+SHIFT), or with the input locale indicator on the taskbar or language bar. The language bar is an on-screen control with which the user can configure a text service. (See How to show the language bar.) The following screen shot shows a language selection list that is displayed when the user clicks on the locale indicator.

Input locale indicator on the Windows taskbar

When the IMM sends a WM_INPUTLANGCHANGE message, CDXUTIMEEditBox must perform several important tasks:

  1. The GetKeyboardLayout method is called to return the input locale identifier (ID) for the application thread. The CDXUTIMEEditBox class saves this ID in its static member variable s_hklCurrent for later use. It is important for the application to know the current input locale, because the IME for each language has its own distinct behavior. The developer may need to provide different code for different input locales.
  2. CDXUTIMEEditBox initializes a string to display in the edit box language indicator. This indicator can display the active input language when the application is running in full-screen mode and neither the taskbar nor language bar is visible.
  3. The ImmGetConversionStatus method is called to indicate whether the input locale is in native or non-native conversion mode. Native conversion mode lets the user enter text in the chosen language. Non-native conversion mode makes the keyboard act as a standard English keyboard. It is important to give the user a visual cue as to what type of conversion mode the IME is in, so that the user can easily know what characters to expect when hitting a key. CDXUTIMEEditBox provides this visual cue with a language indicator color. When the input locale uses an IME with native conversion mode, the CDXUTIMEEditBox class draws the indicator text with the color defined by the m_IndicatorImeColor parameter. When the IME is in non-native conversion mode, or no IME is used at all, the class draws the indicator text with the color defined by the m_IndicatorEngColor parameter.
  4. CDXUTIMEEditBox checks the input locale and sets the static member variable s_bInsertOnType to TRUE for Korean and FALSE for all other languages. This flag is required because of the different behaviors of Korean IMEs and all other IMEs. When entering characters in languages other than Korean, the user-entered text is displayed in the composition window, and the user can freely change the content of the composition string. The user presses the ENTER key when satisfied with the composition string, and the composition string is sent to the application as a series of WM_CHAR messages. In Korean IMEs, however, when a user presses a key to enter text, a character is immediately sent to the application. When the user subsequently presses more keys to modify that initial character, the character in the edit box changes to reflect additional input from the user. Essentially, the user is composing characters in the edit box. These two behaviors are different enough that CDXUTIMEEditBox must code for each of them specifically.
  5. The static member method SetupImeApi is called to retrieve addresses of two functions from the IME module: GetReadingString and ShowReadingWindow. If these functions exist, ShowReadingWindow is called to hide the default reading window for this IME. Because the application renders the reading window itself, it notifies the IME to disable drawing the default reading window so that it will not interfere with full-screen rendering.

WM_IME_SETCONTEXT

The IMM sends a WM_IME_SETCONTEXT message when a window of the application is activated. The lParam parameter of this message contains a flag that indicates to the IME which windows should get drawn and which should not. Because the application is handling all of the drawing, it does not need the IME to draw any of the IME windows. Therefore, the application's message handler simply sets lParam to 0 and returns.

WM_IME_STARTCOMPOSITION

The IMM sends a WM_IME_STARTCOMPOSITION message to the application when an IME composition is about to begin as a result of keystrokes by the user. If the IME uses the composition window, it displays the current composition string in a composition window. CDXUTIMEEditBox handles this message by performing two tasks:

  1. CDXUTIMEEditBox clears the composition string buffer and attribute buffer. These buffers are static members of CDXUTIMEEditBox.
  2. CDXUTIMEEditBox sets the s_bHideCaret static member variable to TRUE. This member, defined in the base CDXUTEditBox class, controls whether the cursor in the edit box should be drawn when the edit box is rendered. The composition window functions similarly to an edit box with text and cursor. To avoid confusion when the composition window is visible, the edit box hides its cursor so that only one cursor is visible at a time.

WM_IME_COMPOSITION

The IMM sends a WM_IME_COMPOSITION message to the application when the user enters a keystroke to change the composition string. The value of lParam indicates what type of information the application can retrieve from the Input Method Manager (IMM). The application should retrieve the available information by calling ImmGetCompositionString and then should save the information in its private buffer so that it can render the IME elements later.

CDXUTIMEEditBox checks for and retrieves the following composition string data:

WM_IME_COMPOSITION lParam Flag ValueDataDescription
GCS_COMPATTRComposition AttributeThis attribute contains information such as the status of each character in the composition string (for example, converted or non-converted). This information is needed because CDXUTIMEEditBox colors the composition string characters differently based upon their attributes.
GCS_COMPCLAUSEComposition Clause InformationThis clause information is used when the Japanese IME is active. When a Japanese composition string is converted, characters may be grouped together as a clause that gets converted to a single entity. When the user moves the cursor, CDXUTIMEEditBox uses this information to highlight the entire clause, instead of just a single character within the clause.
GCS_COMPSTRComposition StringThis string is the up-to-date string being composed by the user. This is also the string displayed in the composition window.
GCS_CURSORPOSComposition Cursor PositionThe composition window implements a cursor, similar to the cursor in an edit box. The application can retrieve the cursor position when processing the WM_IME_COMPOSITION message in order to draw the cursor properly.
GCS_RESULTSTRResult StringThe result string is available when the user is about to complete the composition process. This string should be retrieved and the characters should be sent to the edit box.

WM_IME_ENDCOMPOSITION

The IMM sends a WM_IME_ENDCOMPOSITION message to the application when the IME composition operation is ending. This can occur when the user presses the ENTER key to approve the composition string, or the ESC key to cancel the composition. CDXUTIMEEditBox handles this message by setting the composition string buffer to be empty. It then sets s_bHideCaret to FALSE because the composition window is closed and the cursor in the edit box should again be visible.

The CDXUTIMEEditBox message handler also sets s_bShowReadingWindow to FALSE. This flag controls whether the class draws the reading window when the edit box renders itself, so it must be set to FALSE when a composition ends.

WM_IME_NOTIFY

The IMM sends a WM_IME_NOTIFY message to the application whenever an IME window changes. An application that handles the drawing of the IME windows should process this message so that it is aware of any update to the content of the window. The wParam indicates the command or the change that is taking place. CDXUTIMEEditBox handles the following commands:

IME CommandDescription
IMN_SETOPENSTATUSSent to the application when the open status of the input context is changed. For a language that uses IME, this command can be sent when the user changes from native conversion mode to non-native, or vice versa. (See WM_INPUTLANGCHANGE for definitions of native and non-native modes.) CDXUTIMEEditBox handles this command similar to the way it handles WM_INPUTLANGCHANGE. It must retrieve the current input language and conversion mode, and it must initialize the indicator text and color.
IMN_OPENCANDIDATE / IMN_CHANGECANDIDATESent to the application when the candidate window is about to be opened or updated, respectively. The candidate window opens when a user wishes to change the converted text choice. The window is updated when a user moves the selection indicator or changes the page. CDXUTIMEEditBox uses one message handler for both of these commands because the tasks required are exactly the same:
  1. CDXUTIMEEditBox sets the bShowWindow member of the candidate list structure s_CandList to TRUE to indicate that the candidate window needs to be drawn during frame rendering.
  2. CDXUTIMEEditBox retrieves the candidate list by calling ImmGetCandidateList, first to get the required buffer size, and then again to get the actual data.
  3. The private candidate list structure s_CandList is initialized with the retrieved candidate data.
  4. The candidate strings are stored as an array of strings.
  5. The index of the selected entry, as well as the page index, is saved.
  6. CDXUTIMEEditBox checks whether the candidate window style is vertical or horizontal. If the window style is horizontal, an additional string buffer, the HoriCand member of s_CandList, must be initialized with all of the candidate strings, with space characters inserted between all adjacent strings. When rendering a vertical candidate window, the individual candidate strings are drawn one at a time, with the y coordinates incremented for each string. However, this HoriCand string should be used when rendering a horizontal candidate window, because the space character is the best way to separate two adjacent strings on the same line.
IMN_CLOSECANDIDATESent to the application when a candidate window is about to close. This happens when a user has made a selection from the candidate list. CDXUTIMEEditBox handles this command by setting the visible flag of the candidate window to FALSE and then clearing the candidate string buffer.
IMN_PRIVATESent to the application when the IME has updated its reading string as a result of the user typing or removing characters. The application should retrieve the reading string and save it for rendering. CDXUTIMEEditBox has two methods to retrieve the reading string, based upon how reading strings are supported in the IME:
  • If the IME supports the GetReadingString function, GetReadingString is called to retrieve the reading string.
  • If the IME does not implement GetReadingString, CDXUTIMEEditBox retrieves the reading string from the input context content.

Rendering

Rendering of the IME elements and windows is straightforward. CDXUTIMEEditBox lets the base class render first because IME windows should appear on top of the edit control. After the base edit box is rendered, CDXUTIMEEditBox checks the visibility flag of each IME window (indicator, composition, candidate, and reading window) and draws the window if it should be visible. See Default IME Behavior for descriptions of the different IME window types.

Input Locale Indicator

The input locale indicator is rendered before any other IME windows because it is an element that is always displayed. It should therefore appear below other IME windows. CDXUTIMEEditBox renders the indicator by calling the RenderIndicator method, in which the indicator font color is determined by examining the s_ImeState static variable, which reflects the current IME conversion mode. When the IME is enabled and native conversion is active, the method uses m_IndicatorImeColor as the indicator color. If the IME is disabled or is in non-native conversion mode, m_IndicatorImeColor is used to draw the indicator text. By default, the indicator window itself is drawn to the right of the edit box. Applications can change this behavior by overriding the RenderIndicator method.

The following figure shows the different appearances of an input locale indicator for English, Japanese in alphanumeric conversion mode, and Japanese in native conversion mode:

IME locale indicators

Composition Window

The drawing of the composition window is handled in the RenderComposition method of CDXUTIMEEditBox. The composition window floats above the edit box. It should be drawn at the cursor position of the underlying edit control. CDXUTIMEEditBox handles the rendering as follows:

  1. The entire composition string is drawn using the default composition string colors.
  2. Characters with certain special attributes should be drawn in different colors, so CDXUTIMEEditBox reviews the characters of the composition string and inspects the string attribute. If the attribute calls for different colors, the character is drawn again with the appropriate colors.
  3. The cursor of the composition window is drawn to complete the rendering.

The cursor should blink for Korean IMEs, but it should not for other IMEs. RenderComposition determines whether the cursor should be visible based upon timer values when the Korean IME is used.

Reading and Candidate Windows

The reading and candidate windows are rendered by the same CDXUTIMEEditBox method, RenderCandidateReadingWindow. Both windows contain an array of strings for vertical layout, or a single string in the case of horizontal layout. The bulk of the code in RenderCandidateReadingWindow is used to position the window so that no part of the window falls outside the application window and gets clipped.

Limitations

IMEs sometimes contain advanced features to improve the ease of inputting text. Some of the features found in newer IMEs are shown in the following figures. These advanced features are not present in DXUT. Implementing support for these advanced features can be challenging because there is no interface defined to obtain the necessary information from the IMEs.

Advanced Traditional Chinese IME with expanded candidate list:

Advanced IME for Traditional Chinese

Advanced Japanese IME with some candidate entries that contain additional text to describe their meanings:

Advanced IME for Japanese

Advanced Korean IME that includes a handwriting recognition system:

Advanced IME for Korean

Registry Information

The following registry information is checked to determine the orientation of the reading window, when the current IME is older CHT New Phonetic that doesn't implement GetReadingString().

KeyValue
HKCU/software/microsoft/windows/currentversion/IME_Namekeyboard mapping

Where: IME_Name is MSTCIPH if the IME file version is 5.1 or later; otherwise IME_Name is TINTLGNT.

The orientation of reading window is horizontal if either:

  • The IME is version 5.0 and keyboard mapping value is 0x22 or 0x23
  • The IME is version 5.1 or version 5.2 and keyboard mapping value is 0x22, 0x23 or 0x24.

If neither condition is met, the reading window is vertical.

Appendix A: CHT Versions per Operating System

Operating SystemCHT IME Version
Windows 984.2
Windows 20004.3
unknown4.4
Windows ME5.0
Office XP5.1
Windows XP5.2
Standalone web downloadble6.0

Further Information

For additional information, see the following:

GetReadingString

Gets reading string information.

Parameters
himc
[in] Input context.
uReadingBufLen
[in] Length of lpwReadingBuf, in WCHAR. If it is zero, it means query reading buffer length.
lpwReadingBuf
[out] Return reading string (not zero end).
pnErrorIndex
[out] Return index of error character in the reading string if there is.
pfIsVertical
[out] If it is TRUE, reading UI is vertical. Otherwise, horizontal puMaxReadingLen.
puMaxReadingLen
[out] The reading UI length.The max reading length is not fixed; it depends not only on keyboard layout, but also on input mode (for example, internal code, surrogate input).
Return Values

The reading string length.

Remarks

If return value > uReadingBufLen, then all OUT parameters are undefined.

This function is implemented in CHT IME 6.0 or later, and can be acquired by GetProcAddress() on an IME module handle; the IME module handle can be acquired by ImmGetIMEFileName() and LoadLibrary().

Requirements

Header: Declared in Imm.h.

Import Library: Use Imm.lib.

ShowReadingWindow

Show (or hide) the reading window.

Parameters
himc
[in] Input context.
bShow
[in] Set to True to show the reading window (or False to hide it).
Return Values

Return TRUE if success, FALSE otherwise.

Remarks

This function is implemented in CHT IME 6.0 or later, and can be acquired by GetProcAddress() on an IME module handle; the IME module handle can be acquired by ImmGetIMEFileName() and LoadLibrary().

Requirements

Header: Declared in Imm.h.

Import Library: Use Imm.lib.  

Godot引擎界面与核心操作全解析:从节点系统到高效开发 游戏引擎是现代游戏开发的核心工具,它通过可视化的编辑器和脚本系统,将复杂的图形渲染、物理模拟、音频处理等底层技术封装成开发者友好的接口。其核心原理在于场景图(Scene Graph)和组件化架构,通过节点(Node)的层级组合来构建游戏对象,这种设计大幅提升了代码复用性和项目可维护性。在技术价值上,它降低了开发门槛,使独立开发者和中小团队也能高效创作2D/3D内容。Godot引擎正是这一理念的杰出代表,其界面设计紧密围绕“场景-节点”哲学,将编辑器、脚本系统和资源管理器深度整合。对于初学者而言,掌握其项目管 阅读详情

相关推荐

Unity单元测试框架全解析:从UTF到Moq的实战指南

单元测试是软件工程中保障代码质量的核心实践,通过对代码最小可测试单元进行自动化验证,确保其行为符合预期。其原理在于隔离被测逻辑,通过预设输入与断言输出来验证功能正确性。在游戏开发领域,单元测试的技术价值尤为突出,它能有效防止回归错误、提升代码可维护性,并为安全重构提供信心。Unity作为主流的游戏开发引擎,其项目结构混合了C#逻辑与引擎生命周期,对单元测试提出了特殊挑战。因此,掌握适配Unity的测试框架与编写可测试代码的方法,成为开发者提升工程能力的关键。本文聚焦Unity Test Framework

weixin_30470643的博客 330

[Imm]Imm API学习笔记——GCS常数

GCS常数是什么东西?当你在输入法打开状态时敲键盘,输入法会尝试将你输入的内容转为中文字符(这个过程称为Composition——组字),然后向窗口发送WM_IME_COMPOSITION通知当前的组字状态(lParam参数),然后用户可以通过调用ImmGetCompositionString消息得到详细的组字信息。   注意ImmGetCompositionString的dwBufLen参数的

fishmai的专栏 1408

工业机器人关节拆装流程_一文读懂模块化直驱电机及机器人关节模组

私信“干货”二字,即可领取138G伺服与机器人专属及电控资料!如果说芯片是智能行业最为重要的核心元件,那么电机几乎可以说是支撑了整个自动化和大工业生产以及现代社会最为重要的部件,全世界90%的能源是由电机发出来的,而70%是由电机消耗调的,电机可以说是整个人类社会能源循环的占有绝对地位的产品。普通伺服电机伺服电机其实已经算是电动机中比较高端的类型,特别是永磁同步类型的伺服电机,由于其启动快速,惯量...

weixin_32159771的博客 2155

DirectX9 SDK Samples(12) CustomUI Sample

这一次的例子是关于DXUT的UI。下面先翻译文档中的比较重要的说明。 这个例子开始时定义了两个CDXUTDialog对象:g_HUD和g_SampleUI。一个CDXUTDialog是一个装入了一个或多个控件(按钮等)的容器。对话框(CDXUTDialog)位于程序和控件之间。因此程序可以传递信息和渲染命令给对话框,而对话框保证它的所有控件能够正确收到信息和得到渲染。控件是设计成要和对话框一起使

1732

【HarmonyOS 5】鸿蒙APP使用【团结引擎Unity】开发的案例教程

以下是基于团结引擎开发鸿蒙Unity应用的详细案例教程,整合环境配置、工程适配、跨语言通信等核心环节。

2201_75709314的博客 2483

The moving least square approximation(MLS).

移动最小二乘法, moving least square

fanglovel的博客 299

D3D9 Samples(15)--CustomUI

D3D9 Samples(15)--CustomUI              打开CustomUI项目。编译运行:             这个例子展示了DXUT提供的GUI系统。在dialog中展示各种控件的用法。     1. 对话框CDXUTDialog   1.1 初始化   InitApp g_SampleUI.Init( &g_DialogRes

TechTiger的博客 1999

【自适应滤波】自适应UKF,基于新息自适应调节Q和R,场景为雷达跟踪与滤波、MATLAB实现

本文提出了一种基于新息协方差匹配的自适应UKF(CM-AUKF)算法,用于解决噪声统计未知或时变场景下的目标跟踪问题。通过实时调整过程噪声协方差Q和观测噪声协方差R,CM-AUKF显著提升了跟踪精度和稳定性。仿真结果表明,相比传统UKF,CM-AUKF在位置和速度估计误差上分别降低了约50%和30%,且无需人工调参。该算法适用于无人机导航、雷达跟踪等动态环境,MATLAB代码可直接运行复现结果。自适应曲线显示算法能有效收敛到真实噪声参数,验证了其自适应能力。

985工科博士毕业,专攻定位、导航和滤波等算法研究。从业10年,主要使用MATLAB 330

Matlab 2024a安装卡在准备阶段?系统级适配指南

MATLAB安装失败常被误判为网络或硬件问题,实则源于现代科学计算软件对操作系统底层环境的深度依赖。其核心原理在于安装器需协同Windows服务、TLS协议栈、证书信任链及权限模型共同工作。技术价值体现在保障许可验证可靠性、提升组件部署一致性、避免运行时权限中断。典型应用场景包括高校实验室批量部署、企业HPC环境集成、以及科研仿真平台标准化建设。尤其当遇到‘正在准备安装’长期停滞、证书校验失败或VC++/NET Framework版本不兼容时,本质是Java 17重构的Installer 2.0与系统环境失

weixin_30781107的博客 571

十五、SAP-物料需求计划(MRP)

业务逻辑、功能讲解、图文解析、章节总结

m0_72403327的博客 1095

C#量化交易的市场数据采集与分析:从0到1构建你的‘数据雷达’——对比5大神器,代码实战全解析!

数据是量化交易的‘氧气’,而好的数据采集与分析是你的‘呼吸机’!本文5大神器+代码实战,总有一款适合你!(本文代码均经过测试,但请根据实际需求调整!

java专栏 734

在 VS Code 里画 Draw.io:图在编辑器中完成,直接进仓库

vscode-drawio 把 Draw.io 画布搬进 VS Code:打开 `.drawio` 文件即可直接绘图,文件本身是纯 XML,git 里 diff 清晰,还能另存为 `.drawio.svg` 或 `.drawio.png` 直接嵌进 README,无需导出。 [![VS Code Draw.io 扩展绘图与保存演示](https://raw.gitcode.com/gh_mirr

gitblog_00574的博客 427

在轻量化与精度之间取得平衡:YOLOv8 + GhostNet 的设计与实验分析

摘要: GhostNet系列(GhostNet、GhostNetv2、GhostNeXt)通过“幽灵特征图”技术,以极低计算量生成丰富特征,为YOLOv8提供轻量化改造方案。该技术能在减少参数量与计算量的同时保持或提升检测精度,适用于边缘设备部署。实现时需替换YOLOv8的Backbone为GhostNet模块,并通过消融实验验证其有效性。实验数据表明,改造后的模型在参数量降低30%的同时,推理速度提升28.6%,mAP@0.5最高提升1.9个百分点,平衡了轻量化与精度,为毕设提供技术创新性与工程落地性的双

m0_64661770的博客 194

Unity插件框架开发指南:从零构建高内聚低耦合的模块化游戏架构

在游戏开发领域,模块化架构是实现代码复用和团队高效协作的关键技术。其核心原理是通过定义清晰的接口和通信机制,将不同功能解耦为独立模块,从而实现高内聚、低耦合的设计目标。这种架构的技术价值在于显著提升项目的可维护性、可扩展性和团队并行开发效率。在Unity游戏开发中,插件框架是模块化思想的工程实践,它允许开发者将成就系统、UI框架等功能封装为独立插件,通过事件驱动或服务定位等模式与主程序交互。本文聚焦于Unity插件框架的实现,详细阐述了如何利用Assembly Definition进行程序集隔离,构建事件总

weixin_30938149的博客 316

将指定文件夹下每张用LabelImg标注的图片中标注部分抠出来保存到指定文件夹下。

将指定文件夹下每张用LabelImg标注的图片中标注部分抠出来保存到指定文件夹下。

weixin_44119674的博客 440

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Unity.XR.OpenVR实战指南:从核心API到高频错误排查

在VR应用开发中,输入系统和姿态追踪是构建沉浸式体验的核心技术。输入系统通过抽象层管理用户交互,而姿态追踪则负责实时捕捉头显与控制器的空间位置,其底层原理依赖于传感器数据融合与空间定位算法。这些技术的价值在于为开发者提供了稳定、跨设备的交互基础,极大地提升了VR应用的可用性与用户体验。在Unity引擎中,通过集成SteamVR运行时,开发者可以高效实现复杂的VR交互逻辑,例如手柄控制、手势识别与物理反馈。本文聚焦于Unity.XR.OpenVR插件的实战应用,深入解析Action系统配置、追踪原点设置等关键

weixin_34408624的博客 469

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Godot 4.4开发规范与AI助手配置:提升团队协作与代码质量

在游戏开发中,建立清晰的开发规范是保障项目可维护性和团队协作效率的基石。其核心原理在于通过统一的文件结构、编码约定和场景组织准则,为代码库建立可预测的、一致的结构,从而降低理解成本与技术债务。从技术价值看,这不仅提升了代码的可读性与可维护性,也为自动化工具链和高效协作铺平了道路。在实际应用场景中,结合现代AI编码助手,开发者可以将规范内化为自动化的工作流,从而将精力从重复的样板代码和语法查询中解放出来,更专注于游戏逻辑与创新。本文聚焦于Godot 4.4引擎,详细阐述了如何制定GDScript 2.0编码规

weixin_30664615的博客 468

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Godot游戏开发实战:集成Supabase云端数据库实现玩家数据持久化

在游戏开发中,数据持久化是构建现代游戏体验的核心需求,它确保了玩家进度、设置和成就的长期保存。其原理是通过网络将本地数据同步到远程服务器,实现跨设备和跨会话的数据一致性。这项技术的价值在于为游戏增添了社交性、竞争性和连续性,是构建排行榜、云存档和社交功能的基础。在应用场景上,无论是独立游戏还是大型多人在线游戏,都需要可靠的后端服务来处理玩家数据。Supabase作为一个基于PostgreSQL的开源后端即服务(BaaS)平台,提供了实时数据库和RESTful API,与Godot引擎的轻量级特性完美契合。通

hqmln的博客 358

自带IDE和脚本语言的游戏引擎:垂直整合如何重构开发流程

在游戏开发工具链中,效率提升往往不只依赖渲染性能,更取决于语言、编辑器和运行时之间的协同。自研脚本语言并非炫技,而是为了打通类型检查、调试、序列化与热重载等关键环节;自带IDE也不只是提供一个代码编辑器,而是让场景与代码在同一数据模型下双向联动。这种垂直整合能显著降低开发者频繁切换工具的隐性成本,让独立开发者和小团队更专注于内容创作。本文从通用技术原理出发,拆解全家桶式游戏引擎的架构协作逻辑,分析其适用边界,并结合工程实践给出选型评估与设计建议,可帮助技术决策者理解此类工具的价值边界,也能为有意自建轻量级工

weixin_30326741的博客 325

Unity VR开发终极指南:从核心交互到性能优化的10个实战技巧

虚拟现实(VR)开发通过构建沉浸式三维环境,为用户提供身临其境的体验,其核心在于实时渲染与低延迟交互。其技术原理依赖于高性能图形引擎、精确的空间定位与追踪系统,以及自然的用户输入处理。在工程实践中,Unity引擎因其跨平台能力和完善的XR工具链,成为实现这些技术价值的首选平台,它能有效降低开发门槛,提升内容生产效率。在应用场景上,从VR游戏、工业仿真到虚拟培训,Unity都能提供稳定支持。本文聚焦于Unity VR开发中的核心模块,详细解析了XR交互系统(XR Interaction Toolkit)的搭建

weixin_30363509的博客 493

从零掌握SteamVR Unity插件:构建PC VR应用的核心指南

虚拟现实(VR)应用开发的核心在于实现用户与虚拟世界的自然交互,其技术基础依赖于精确的空间定位与动作捕捉。在PC VR领域,SteamVR作为开源的追踪与输入系统,已成为连接各类硬件与内容的标准接口。通过将物理控制器的复杂输入(如按键、触摸板、摇杆)抽象为统一的逻辑“动作”,开发者得以跨越设备差异,专注于交互逻辑本身。Unity引擎凭借其强大的跨平台能力和友好的开发环境,与SteamVR插件结合,为开发者提供了从场景搭建、输入处理到物理交互的一站式解决方案。这种组合极大地降低了VR开发门槛,使得实现如物体抓

aoe41606的博客 498

Unity Mirror网络框架入门:从PlayerTest示例解析多人游戏同步原理

网络同步是实时多人游戏开发的核心技术,它基于客户端-服务器架构,通过权威服务器确保游戏状态的一致性。其原理在于服务器接收客户端指令,处理游戏逻辑,并将结果同步给所有客户端。这项技术的价值在于为玩家提供公平、流畅的多人互动体验,广泛应用于多人在线游戏、协作应用等场景。本文以Unity中热门的Mirror网络框架为例,通过剖析其经典的PlayerTest示例,深入讲解NetworkManager、NetworkBehaviour、Command与ClientRpc等核心概念,帮助开发者快速掌握多人游戏同步的基础

weixin_34245749的博客 304

Java 23 种设计模式

/ 产品族:Button + TextField 是一套// Windows 风格} }} }// Mac 风格} }} }// 抽象工厂 — 创建产品族一句话:普通工厂一个方法一种产品,抽象工厂一个方法多个关联产品。// 计算 "1 + 2 - 3"right = r;// 使用// 3一句话:很少用,JDK 的就是。创建型 — 怎么 new单例(一个)→ 工厂(子类决定)→ 抽象工厂(产品族)→ 建造者(分步构造)→ 原型(克隆)结构型 — 类/对象怎么组合。

鲜衣怒马少年时,不负韶华行且知。 从第一个Hello World起,便踏上这条后端修行路。趟过分布式事务的浑水,翻过性能瓶颈的高山,方知代码如剑,需千锤百炼方显锋芒。 博客所记,皆为修行路上的顿悟与磕绊,愿与同道人共勉,稳步江湖。 321

Unity IL2CPP下自动翻译插件兼容性解决方案

在Unity游戏开发中,反射机制是实现动态功能的重要技术手段,它允许程序在运行时检查和操作类型信息。然而,当项目切换到IL2CPP脚本后端时,其AOT编译和代码剪裁特性会限制反射功能,导致依赖反射的自动翻译插件在真机环境失效。这一技术冲突的核心在于IL2CPP为优化性能和包体大小,会移除未被静态分析引用的代码。为解决此问题,开发者需要掌握通过link.xml配置文件和Preserve属性来引导IL2CPP保留必要代码的方法,同时重构插件逻辑以减少运行时反射依赖。这些实践对于确保多语言游戏在移动端的稳定运行至

weixin_30509393的博客 317
上一篇: 物體的移動
下一篇: X文件的使用(完整)
ShowLong
博客等级 码龄21年 61粉丝 67原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值