หมายเหตุนี้อธิบายวิธีการใช้แมโครที่แปลง MBCS/Unicode ซึ่งกำหนดไว้ใน AFXPRIVH.แมโครนี้จะมีประโยชน์มากที่สุดถ้า deals แอพลิเคชันของคุณได้โดยตรง กับการ OLE API หรือเหตุผลบางประการ มักต้องการแปลงระหว่าง Unicode และ MBCS?
ภาพรวม
ใน MFC 3.x, DLL พิเศษถูกใช้ (MFCANS32DLL) การแปลงระหว่าง Unicode และ MBCS โดยอัตโนมัติเมื่อ OLE อินเทอร์เฟซที่ถูกเรียกว่า DLL นี้เป็นชั้นที่เกือบโปร่งใสที่ได้รับการอนุญาตให้โปรแกรมประยุกต์ OLE การเขียนว่า OLE APIs และอินเทอร์เฟซถูก MBCS ถึงแม้ว่าพวกเขาจะเสมอ Unicode (ยกเว้นบน Macintosh) ขณะที่อยู่ในชั้นนี้สะดวก และอนุญาตให้โปรแกรมประยุกต์สามารถ ported อย่างรวดเร็วจากของ Win16 เพื่อ Win32 (MFC, Microsoft Word, Microsoft Excel และ VBA เป็นเพียงบางส่วนของโปรแกรมประยุกต์ของ Microsoft ที่ใช้เทคโนโลยีนี้), ยังมีประสิทธิภาพการทำงานบางครั้งสำคัญในการเข้าชม ด้วยเหตุนี้ MFC 4.x ใช้ DLL นี้ และแทน พูดคุยโดยตรงกับอินเทอร์เฟซ Unicode OLE สำหรับ การทำเช่นนี้ MFC จำเป็นต้องแปลงเป็น Unicode mbcs ได้เมื่อทำการโทรไปยังอินเทอร์เฟซ OLE และมักจะต้องแปลง mbcs ได้จาก Unicode เมื่อใช้อินเทอร์เฟซ OLE เพื่อจัดการสิ่งนี้ได้อย่างมีประสิทธิภาพ และง่ายดาย หมายเลขของแมโครที่สร้างขึ้นเพื่อทำการแปลงนี้ได้ง่าย?
หนึ่ง hurdles ใหญ่ที่สุดของการสร้างเช่นชุดของแมโครคือการจัดสรรหน่วยความจำ เนื่องจากไม่สามารถแปลงสายอักขระในสถานที่ หน่วยความจำใหม่เพื่อเก็บผลลัพธ์แปลงแล้วต้องสามารถจัดสรร นี้ไม่สามารถถูกเสร็จกับโค้ดที่คล้ายกับต่อไปนี้:
/ / เราต้องการจะแปลงสตริ MBCS ใน lpszA
int nLen = MultiByteToWideChar (CP_ACP, 0, lpszA, -1, NULL, NULL);
LPWSTR lpszW = WCHAR ใหม่ [nLen];
MultiByteToWideChar (CP_ACP, 0, lpszA, -1, lpszW, nLen);
/ / ใช้เรียก OLE ที่นี่
pI-gtSomeFunctionThatNeedsUnicode(lpszW)
/ / ฟรีสายอักขระ
ลบ[] lpszW(&G)
วิธีการนี้เป็นตัวเลขของปัญหา ปัญหาหลักคือว่า มันมากการเขียน ทดสอบ และการดีบักรหัส สิ่งที่ถูกเรียกฟังก์ชันที่ง่าย มีความซับซ้อนมาก นอกจากนี้ มี runtime สำคัญค่าใช้จ่ายในการทำเช่นนั้น หน่วยความจำมีการปันส่วนในกอง และรอดแต่ละครั้งที่การแปลงเสร็จเรียบร้อยแล้ว สุดท้าย รหัสข้างต้นจะต้องมีความเหมาะสม #ifdefs เพิ่มสำหรับสร้าง Unicode และ Macintosh (ซึ่งไม่จำเป็นต้องแปลงนี้เกิดขึ้น)?
โซลูชั่นเรามาขึ้นกับการ สร้างแมโครบางรหัสต้นทางที่ 1) รูปแบบความแตกต่างระหว่างสถาปัตยกรรม และต่าง ๆ 2) ใช้แบบแผนการจัดสรรหน่วยความจำที่มีประสิทธิภาพ และ 3) ไม่ง่ายที่จะแทรกลงในที่ที่มีอยู่ได้ นี่คือตัวอย่างของข้อกำหนดอย่างใดอย่างหนึ่ง:
#กำหนด A2W(lpa) (\
nbsp (Lpa (LPCSTR) == NULL) ค่า NULL: (\
_convert = (strlen (lpa) + 1), \
AfxA2WHelper((LPWSTR) alloca(_convert*2), lpa, _convert) \
)\
)(&N)
การใช้แมโครแทนของรหัสข้างต้นและสิ่งนี้จะง่ายกว่ามาก:
/ / ใช้เรียก OLE ที่นี่
USES_CONVERSION
pI-gtSomeFunctionThatNeedsUnicode(T2OLE(lpszA))(&G)
มีสายพิเศษที่จำเป็นต้องมีการแปลง แต่ใช้แมโครที่ได้ง่าย และมีประสิทธิภาพ?
การใช้งานแต่ละแมโคใช้ฟังก์ชัน _alloca() เพื่อการจัดสรรหน่วยความจำจากกองซ้อนแทนของกอง การปันส่วนหน่วยความจำจากกองซ้อนจะเร็วกว่าหน่วยความจำบนกองการปันส่วนมาก และเพิ่มหน่วยความจำโดยอัตโนมัติเมื่อฟังก์ชันคือ exited นอกจากนี้ แมโครการหลีกโทรMultiByteToWideChar (หรือWideCharToMultiByte) มากกว่าหนึ่งครั้ง สามารถทำได้ โดยการปันส่วนหน่วยความจำเพิ่มเติมนิดเดียวมากกว่าที่จำเป็น เราทราบดีว่า MBC ที่จะแปลงเป็นมากที่สุดหนึ่งWCHARและสำหรับแต่ละWCHARเราจะมีตัวอักษรได้สูงสุดสอง MBC ไบต์ โดยการปันส่วนแต่เสมอพอเพียงเล็กน้อยมากกว่าจำเป็น การจัดการการแปลงที่สองสายที่สอง เรียกใช้ฟังก์ชันการแปลงถูกตั้ง การโทรไปยังผู้ช่วยเหลือฟังก์ชันAfxA2Whelperช่วยลดจำนวนของอาร์กิวเมนต์ pushes ที่ต้องดำเนินการเพื่อทำการแปลง (นี้เป็นผลรหัสขนาดเล็ก กว่าถ้าจะเรียกว่าMultiByteToWideCharโดยตรง)?
ลำดับสำหรับแมโครให้มีพื้นที่ในการจัดเก็บยาวแบบชั่วคราว จะต้องประกาศตัวแปรท้องถิ่นที่เรียกว่า _convert ที่ทำในแต่ละฟังก์ชันที่ใช้แมโครที่แปลง ทำได้ โดยการเรียกใช้แมโคUSES_CONVERSIONเห็นข้างในตัวอย่างเป็น?
มีทั้งแปลงทั่วไปแมโครและแมโครที่ระบุ OLE มีการกล่าวถึงนี้แมโคที่แตกต่างกันสองชุดด้านล่าง ทั้งหมดของแมโครที่อยู่ใน AFXPRIVH?
แมโครที่แปลงทั่วไป
แมโครที่แปลงทั่วไปแบบฟอร์มต้นแบบกลไก ตัวอย่างแมโครและการใช้งานที่แสดงในส่วนก่อนหน้า A2W คือ โคหนึ่งเช่น "ทั่วไป" มันไม่มีความสัมพันธ์กับ OLE โดยเฉพาะ ชุดของแมโครทั่วไปอยู่ในรายการด้านล่าง:
A2CW (LPCSTR) - gt (LPCWSTR)
A2W (LPCSTR) - > (LPWSTR)
W2CA (LPCWSTR) - > (LPCSTR)
W2A (LPCWSTR) - > (LPSTR)
นอกจากทำการแปลงข้อความ ยังมีแมโคร และฟังก์ชันในการช่วยเหลือสำหรับการแปลงTEXTMETRIC, DEVMODE, BSTRและ OLE สตริการปันส่วน แมโครเหล่านี้อยู่นอกเหนือขอบเขตของการสนทนานี้ หมายถึง AFXPRIVH สำหรับข้อมูลเพิ่มเติมเกี่ยวกับแมโครเหล่านั้น?
OLE แปลงแมโคร
แมโครที่แปลง OLE ถูกออกแบบมาเป็นพิเศษสำหรับการจัดการฟังก์ชันซึ่งคาดว่าอักขระOLESTR ถ้าคุณตรวจสอบส่วนหัวของ OLE คุณจะเห็นจำนวนมากที่อ้างอิงถึงLPCOLESTRและOLECHAR ชนิดเหล่านี้ถูกใช้เพื่ออ้างอิงถึงชนิดของอักขระที่ใช้ในอินเทอร์เฟซ OLE ในทางที่ไม่ใช่เฉพาะแพลตฟอร์ม แมปOLECHARอักขระไม่ในสถาปัตยกรรมของ Win16 และ Macintosh และWCHARใน Win32?
เพื่อลดจำนวนของไดเรกทีฟฐาน#ifdefในรหัส MFC ให้น้อย เรามีโคที่คล้ายกันสำหรับแต่ละแปลงที่ที่เกี่ยวข้องสตริ OLE แมโครในดังต่อไปนี้จะถูกใช้บ่อยที่สุด:
T2COLE (LPCTSTR) - gt (LPCOLESTR)
T2OLE (LPCTSTR) - > (LPOLESTR)
OLE2CT (LPCOLESTR) - > (LPCTSTR)
OLE2T (LPCOLESTR) - > (LPCSTR)
อีกครั้งมีแมโครที่คล้ายกันสำหรับทำTEXTMETRIC, DEVMODE, BSTRและ OLE สายอักขระที่มีการปันส่วน ถึง AFXPRIVH สำหรับข้อมูลเพิ่มเติม?
ข้อควรพิจารณาอื่น ๆ
ไม่ต้องใช้แมโครในแบบวนซ้ำที่แน่นหนา ตัวอย่างเช่น คุณไม่ต้องการเขียนรหัสชนิดต่อไปนี้:
โมฆะ BadIterateCode(LPCTSTR lpsz)
{
USES_CONVERSION
สำหรับ (int ii = 0; ii lt; 10000; ii ++)
pI - > SomeMethod (ii, T2COLE(lpsz))
}
รหัสข้างต้นอาจมีผลในการปันส่วนเมกะไบต์ของหน่วยความจำบนกองที่ขึ้นอยู่กับว่าเนื้อหาของสตริ lpsz เป็น! nbsp นอกจากนี้มันยังใช้เวลาในการแปลงสายอักขระสำหรับแต่ละคำซ้ำของการวนรอบ ย้ายแทน เช่นแปลงค่าคงที่ของการวนรอบ(&N):
โมฆะ MuchBetterIterateCode(LPCTSTR lpsz)
{
USES_CONVERSION
LPCOLESTR lpszT = T2COLE(lpsz)
สำหรับ (int ii = 0; ii lt; 10000; ii ++)
pI - > SomeMethod (ii, lpszT);
}
สายอักขระไม่ใช่ค่าคง encapsulate เรียกเมธอดเข้าไปในฟังก์ชัน นี้จะทำให้บัฟเฟอร์ที่แปลงการอยู่รอดในแต่ละครั้ง ตัวอย่างเช่น:
โมฆะ CallSomeMethod (int ii, LPCTSTR lpsz)
{
USES_CONVERSION
pI-gtSomeMethod (ii, T2COLE(lpsz))
}
โมฆะ MuchBetterIterateCode2 (LPCTSTR * lpszArray)
{
สำหรับ (int ii = 0; ii < 10000; ii ++)
CallSomeMethod (ii, lpszArray[ii])
}
ไม่ส่งกลับผลลัพธ์ของแมโครใน เว้นแต่ค่าส่งกลับแสดงถึงการทำสำเนาของข้อมูลก่อนที่จะกลับ ตัวอย่าง รหัสนี้จะไม่ถูกต้อง:
LPTSTR BadConvert(ISomeInterface* pI)
{
USES_CONVERSION
LPOLESTR lpsz = NULL
pI-gtGetFileName(&lpsz)
LPTSTR lpszT = OLE2T(lpsz)
CoMemFree(lpsz)
กลับ lpszT / / ไม่ถูกต้อง หน่วยความจำ alloca เก่า
}
รหัสข้างต้นอาจสามารถแก้ไข โดยการเปลี่ยนค่าส่งคืนสิ่งที่คัดลอกค่า:
CString BetterConvert(ISomeInterface* pI)
{
USES_CONVERSION
LPOLESTR lpsz = NULL
pI-gtGetFileName(&lpsz)
LPTSTR lpszT = OLE2T(lpsz)
CoMemFree(lpsz)
กลับ lpszT / / CString ทำให้การคัดลอก
}
แมโครที่ถูกใช้งานง่าย และง่ายต่อการแทรกไว้ในรหัสของคุณ แต่ในขณะที่คุณสามารถทราบได้จากการ caveats ข้างต้น คุณจำเป็นต้องใช้ความระมัดระวังเมื่อใช้?
หมายเหตุด้านเทคนิคตามหมายเลข|nbsp หมายเหตุด้านเทคนิคตามประเภท(&N)