ปัญหาทั่วไปที่เกี่ยวข้องกับการโยกย้าย
หนึ่งในเป้าหมายออกแบบสำหรับระดับชั้น OLE 2 ใน MFC 2.5 (และสูงกว่า) เป็นการรักษามากของสถาปัตยกรรมเดียวกันที่เก็บไว้ใน MFC 2.0 สำหรับการสนับสนุน OLE 1.0 มีผล คลาสที่ OLE เดียวใน MFC 2.0 จำนวนมากยังคงอยู่ใน MFC (COleDocument, COleServerDoc, COleClientItem, COleServerItem) รุ่นนี้ นอกจากนี้ การ APIs ในชั้นเรียนเหล่านี้จำนวนมากเหมือนเหมือนกัน อย่างไรก็ตาม OLE 2 เป็น drastically แตกต่างจาก OLE 1.0 เพื่อให้คุณสามารถคาดว่า รายละเอียดบางอย่างมีการเปลี่ยนแปลง ถ้าคุณคุ้นเคยกับการสนับสนุน OLE1 MFC 2.0 คุณจะรู้สึกที่บ้าน โดยการสนับสนุนของ MFC 2.0?
ถ้าคุณกำลังใช้โปรแกรมประยุกต์ที่มีอยู่ของ MFC/OLE1 และเพิ่มฟังก์ชันการทำงาน OLE 2 คุณควรอ่านหมายเหตุนี้ครั้งแรก หมายเหตุนี้ครอบคลุมปัญหาทั่วไปบางอย่างคุณอาจพบขณะ++:การสร้างพอร์ตของฟังก์ชัน OLE1 MFC/OLE ที่ 2 และจากนั้น กล่าวถึงปัญหาเปิดเผยขณะ++:การสร้างพอร์ตโปรแกรมประยุกต์สองโปรแกรมที่รวมอยู่ใน MFC 2.0: ตัว MFC OLE อย่าง OCLIENTและ HIERSVR?
MFC/มุม มองเอกสารสถาปัตยกรรมที่สำคัญคือ
ถ้าโปรแกรมประยุกต์ของคุณไม่ได้ใช้ของ MFC/มุม มองเอกสารสถาปัตยกรรม และคุณต้องการเพิ่มโปรแกรมประยุกต์ของคุณสนับสนุน OLE 2 ตอนนี้เป็นเวลาที่การย้ายไปยังมุมมองเอกสาร / ประโยชน์ของคลาส OLE 2 ของ MFC จำนวนมากจะรับรู้เฉพาะเมื่อโปรแกรมประยุกต์ของคุณจะใช้สถาปัตยกรรมภายในและคอมโพเนนต์ของ MFC?
การใช้งานเซิร์ฟเวอร์หรือคอนเทนเนอร์โดยไม่ใช้สถาปัตยกรรม MFC จะเป็นไปได้ แต่ไม่แนะนำ?
ใช้ MFC ใช้งานแทนที่เป็นของคุณเอง
MFC "กระป๋องใช้งาน" เรียนเช่นCToolBar, CStatusBarและCScrollViewมีอยู่แล้วภายในกรณีรหัสพิเศษสำหรับการสนับสนุน OLE 2 ดังนั้น ถ้าคุณสามารถใช้คลาเหล่านี้ในโปรแกรมประยุกต์ของคุณ คุณจะประโยชน์จากความพยายามที่ใส่เข้าไปเพื่อให้ OLE ทราบ อีก จะสามารถ "โรของเอง" เรียนที่นี่สำหรับวัตถุประสงค์เหล่านี้ แต่ไม่แนะนำ ถ้าคุณต้องการใช้ฟังก์ชันการทำงานที่คล้ายคลึงกัน MFC โค้ดต้นฉบับเป็นการอ้างอิงที่ยอดเยี่ยมสำหรับใช้จัดการกับบางส่วนของจุดอย่างเข้มงวดขึ้นของ OLE (โดยเฉพาะอย่างยิ่งเมื่อมาเพื่อเปิดใช้งานในสถาน)?
ตรวจสอบตัวอย่างรหัส MFC
มีจำนวนตัวอย่าง MFC ที่มีฟังก์ชันการทำงาน OLE แต่ละโปรแกรมประยุกต์เหล่านี้ใช้ OLE จากมุมแตกต่างกัน:
HIERSVR - ส่วนใหญ่สำหรับใช้เป็นเซิร์ฟเวอร์โปรแกรมประยุกต์ จะถูกรวมอยู่ใน MFC 2.0 เป็นโปรแกรมประยุกต์ MFC/OLE1 และถูก ported MFC/OLE 2 และขยายเช่นว่านั้นใช้ OLE คุณลักษณะหลายอย่างใน OLE 2?
OCLIENT - นี้เป็นโปรแกรมประยุกต์แบบสแตนด์อโลนคอนเทนเนอร์ เพื่อแสดงคุณสมบัติ OLE จากการยืนคอนเทนเนอร์ มันเกินไปถูก ported จาก MFC 2.0 แล้ว ขยายการสนับสนุนขั้นสูงเพิ่มเติม OLE คุณลักษณะมากมาย เช่นรูปแบบการกำหนดเองคลิปบอร์ดและการเชื่อมโยงไปยังรายการที่ฝังตัว?
DRAWCLI - แอพลิเคชันนี้ใช้ OLE คอนเทนเนอร์สนับสนุนมากเหมือนไม่ OCLIENT ยกเว้นว่าภายในกรอบของโปรแกรมที่มีอยู่เชิงวัตถุรูปวาดนั้น แสดงวิธีอาจใช้ OLE คอนเทนเนอร์สนับสนุน และรวมลงในโปรแกรมประยุกต์ที่มีอยู่ของคุณ?
SUPERPAD - โปรแกรมประยุกต์นี้ ตลอดจนการประยุกต์แบบสแตนด์อโลนที่ดี มีเซิร์ฟเวอร์ OLE การสนับสนุนเซิร์ฟเวอร์ดังกล่าวใช้ได้ค่อนข้าง minimalist ความสนใจเฉพาะของวิธีใช้บริการคลิปบอร์ด OLE เพื่อคัดลอกข้อมูลไปยังคลิปบอร์ด แต่ใช้หน้าที่การใช้งานที่อยู่ภายใน Windows "แก้ไข" ควบคุมการใช้คลิปบอร์ดวางฟังก์ชัน นี้แสดงส่วนผสมน่าสนใจของการใช้งาน Windows API แบบดั้งเดิมรวมทั้งการรวมกับตัวใหม่ OLE APIs?
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับแอปพลิเคชั่นตัวอย่างดูวิธีการ "MFC ตัวอย่างใช้"?
กรณีศึกษา: OCLIENT จาก MFC 2.0
ตามที่กล่าวไว้ข้างต้น OCLIENTถูกรวมอยู่ใน MFC 2.0 และใช้งาน OLE กับ MFC/OLE1 ขั้นตอนที่โปรแกรมประยุกต์นี้ถูกเริ่มต้นด้วยแปลงการใช้คลาสที่ 2 MFC/OLE ถูกอธิบายไว้ด้านล่าง มีเพิ่มจำนวนของคุณลักษณะหลังจากพอร์ตเริ่มต้นเสร็จสมบูรณ์ดี แสดงคลาสที่ MFC/OLE คุณลักษณะเหล่านี้จะไม่สามารถครอบคลุมที่นี่ ดูตัวอย่างตัวเองสำหรับข้อมูลเพิ่มเติมเกี่ยวกับคุณลักษณะขั้นสูงเหล่านั้น?
หมายเหตุnbsp ข้อผิดพลาดในการคอมไพล์เลอร์และกระบวนการขั้นตอนถูกสร้างขึ้น ด้วย Visual c ++ 2.0 ข้อความแสดงข้อผิดพลาดเฉพาะและตำแหน่งที่ตั้งอาจมีการเปลี่ยนแปลงกับ Visual c ++ 4.0 แต่ยังคงข้อมูลแนวคิดที่ถูกต้อง(&N)?
การตั้ง และการเรียกใช้
วิธีการดำเนินการกับพอร์ต OCLIENT ตัวอย่างการ MFC/OLE คือ เริ่มต้น ด้วยการสร้าง และแก้ไขข้อผิดพลาดของคอมไพเลอร์ชัดเจนซึ่งจะส่งผลให้ ถ้าคุณใช้ตัวอย่าง OCLIENT จาก MFC 2.0 และคอมไพล์ภายใต้ MFC รุ่นนี้ คุณจะพบว่า มีไม่แก้ไขข้อผิดพลาดของที่หลาย ข้อผิดพลาดในลำดับการเกิดขึ้นที่อธิบายไว้ด้านล่าง?
คอมไพล์และแก้ไขข้อผิดพลาด
\oclient\mainview.cpp(104): ข้อผิดพลาด C2660: 'วาด': ฟังก์ชันไม่มีพารามิเตอร์ที่ 4
ข้อผิดพลาดแรกเกี่ยวข้องCOleClientItem::Draw MFC/OLE1 ก็เอาพารามิเตอร์เพิ่มเติมมากกว่าที่ใช้รุ่น MFC/OLE พารามิเตอร์เพิ่มขึ้นมักจะไม่จำเป็น และโดยปกติแล้วค่า NULL (เช่นในตัวอย่างนี้) MFC รุ่นนี้โดยอัตโนมัติสามารถกำหนดว่าค่าของ lpWBounds เมื่อ CDC ที่กำลังมีลากการ metafile DC นอกจากนี้ พารามิเตอร์ pFormatDC ไม่จำเป็นเนื่องจากกรอบจะสร้างหนึ่งจาก "คุณลักษณะ DC" ของ pDC ส่งผ่าน ดังนั้นเพื่อแก้ไขปัญหานี้ คุณเพียงแค่เอาทั้งสองพิเศษไม่มีค่าพารามิเตอร์การเรียกรูปวาด?
\oclient\mainview.cpp(273): ข้อผิดพลาด C2065: 'OLE_MAXNAMESIZE': undeclared ระบุ
\oclient\mainview.cpp(273): ข้อผิดพลาด C2057: คาดว่าคงที่นิพจน์
\oclient\mainview.cpp(280): ข้อผิดพลาด C2664: 'CreateLinkFromClipboard': ไม่สามารถแปลงพารามิเตอร์ 1 จาก 'char [1]' เป็น ' enum:: tagOLERENDER '
\oclient\mainview.cpp(286): ข้อผิดพลาด C2664: 'CreateFromClipboard': ไม่สามารถแปลงพารามิเตอร์ 1 จาก 'char [1]' เป็น ' enum:: tagOLERENDER '
\oclient\mainview.cpp(288): ข้อผิดพลาด C2664: 'CreateStaticFromClipboard': ไม่สามารถแปลงพารามิเตอร์ 1 จาก 'char [1]' เป็น ' enum:: tagOLERENDER '
ข้อผิดพลาดข้างต้นส่งผลจากข้อเท็จจริงว่า ทั้งหมดของฟังก์ชันCOleClientItem::CreateXXXXใน MFC/OLE1 จำเป็นชื่อที่ไม่ซ้ำได้ผ่านการแสดงสินค้า นี้เป็นความต้องการของเครื่องต้นแบบ OLE API นี้ไม่จำเป็นใน MFC/OLE 2 ตั้งแต่ OLE 2 ไม่ใช้ DDE เป็นกลไกในการสื่อสารเป็นต้น (ชื่อที่ใช้ในการสนทนา DDE) เมื่อต้องการแก้ไขปัญหานี้ คุณสามารถเอาออกฟังก์ชันCreateNewNameการอ้างอิงทั้งหมดเป็นเช่นนั้น เป็นการง่ายในการค้นหาอะไรแต่ละฟังก์ชัน MFC/OLE ถูกต้องในรุ่นนี้โดยวางเคอร์เซอร์ของคุณในการเรียกสาย และกด F1 เพียง?
พื้นที่อื่นที่แตกต่างกันมากคือ การจัดการคลิปบอร์ด OLE 2 กับ OLE1 คุณใช้คลิปบอร์ด Windows APIs โต้ตอบกับคลิปบอร์ด 2 OLE นี้เสร็จ โดยกลไกที่แตกต่างกัน APIs MFC/OLE1 ที่ถือว่า คลิปบอร์ดถูกเปิดก่อนที่จะคัดลอกวัตถุCOleClientItemไปยังคลิปบอร์ด นี้ไม่จำเป็น และจะทำให้เกิดการดำเนินงานคลิปบอร์ด MFC/OLE ทั้งหมดล้มเหลว ขณะที่คุณแก้ไขรหัสเพื่อเอาการอ้างอิงบนCreateNewNameคุณยังควรเอารหัสที่เปิด และปิด Windows คลิปบอร์ด?
\oclient\mainview.cpp(332): ข้อผิดพลาด C2065: 'AfxOleInsertDialog': undeclared ระบุ
\oclient\mainview.cpp(332): ข้อผิดพลาด C2064: คำไม่ได้ประเมินไปยังฟังก์ชัน
\oclient\mainview.cpp(344): ข้อผิดพลาด C2057: คาดว่าคงที่นิพจน์
\oclient\mainview.cpp(347): ข้อผิดพลาด C2039: 'CreateNewObject': ไม่ใช่สมาชิกของ 'CRectItem'
ข้อผิดพลาดเหล่านี้เกิดจากตัวจัดการCMainView::OnInsertObject การจัดการคำสั่ง "แทรกวัตถุใหม่" เป็นพื้นที่อื่นซึ่งสิ่งที่มีการเปลี่ยนแปลงค่อนข้างเป็นบิต ในกรณีนี้ จะง่ายที่สุดเพียงผสานการใช้งานต้นฉบับ ด้วยที่มีให้สำหรับโปรแกรมประยุกต์ OLE คอนเทนเนอร์ใหม่ AppWizard ในความเป็นจริง นี้เป็นเทคนิคที่คุณสามารถใช้กับโปรแกรมประยุกต์อื่น ๆ ที่++:การสร้างพอร์ต MFC/OLE1 คุณแสดงการโต้ตอบ "แทรกวัตถุ" โดยการเรียกฟังก์ชันAfxOleInsertDialog ในรุ่นนี้ คุณสามารถสร้างวัตถุการโต้ตอบCOleInsertObjectและโทรDoModal นอกจากนี้ รายการใหม่ของ OLE ถูกสร้างกับCLSIDตัวแทนของสตริงที่ชื่อคลาส ผลลัพธ์สุดท้ายควรมีลักษณะดังนี้
กล่องโต้ตอบ COleInsertDialog
ถ้า (กล่องโต้ตอบDoModal() ! = IDOK)
nbsp กลับ
BeginWaitCursor()
CRectItem * pItem = NULL
ลอง
{
/ / สร้างวัตถุ c ++
pItem = GetDocument() - > CreateItem()
ASSERT_VALID(pItem)
/ / เตรียมใช้งานสินค้าจากข้อมูลโต้ตอบ
ถ้า (! กล่องโต้ตอบCreateItem(pItem))
AfxThrowMemoryException()
/ / ข้อยกเว้นใด ๆ จะทำ
ASSERT_VALID(pItem)
/ / เรียกใช้วัตถุถ้าเหมาะสม
ถ้า (กล่องโต้ตอบGetSelectionType() == COleInsertDialog::createNewItem)
pItem - > DoVerb(OLEIVERB_SHOW, this)
/ / ปรับปรุงทันที
pItem - > UpdateLink()
pItem - > UpdateItemRectFromServer()
/ / การตั้งค่าการเลือกสินค้าใหม่แทรก
SetSelection(pItem)
pItem - > Invalidate()
}
จุดอ่อน (CException, e)
{ / / ล้างสินค้า
ถ้า (pItem ! = NULL)
GetDocument() - > DeleteItem(pItem)
AfxMessageBox(IDP_FAILED_TO_CREATE)
}
END_CATCH
EndWaitCursor()
หมายเหตุnbsp แทรกวัตถุใหม่อาจจะแตกต่างกันสำหรับโปรแกรมประยุกต์ของคุณ)(&N):
ก็ยังจำเป็นต้องรวม lt;afxodlgs.h > ซึ่งประกอบด้วยการประกาศคลาCOleInsertObjectโต้ตอบเช่นเดียวกับกล่องโต้ตอบการอื่น ๆ มาตรฐานแสดงโดย MFC?
\oclient\mainview.cpp(367): ข้อผิดพลาด C2065: 'OLEVERB_PRIMARY': undeclared ระบุ
\oclient\mainview.cpp(367): ข้อผิดพลาด C2660: 'DoVerb': ฟังก์ชันไม่มีพารามิเตอร์ 1
ข้อผิดพลาดเหล่านี้มีสาเหตุมาจากข้อเท็จจริงที่มีการเปลี่ยนแปลงบางค่าคงที่ OLE1 ใน OLE 2 ถึงแม้ว่าแนวคิด พวกเดียวกัน ในกรณีนี้OLEVERB_PRIMARYได้เปลี่ยนเป็นOLEIVERB_PRIMARY ใน OLE1 และ OLE 2 กริยาหลักคือมักจะดำเนินการ โดยที่บรรจุเมื่อผู้ใช้ดับเบิลคลิบนรายการ?
นอกจากนี้DoVerbตอนนี้ใช้พารามิเตอร์แบบพิเศษ ตัวชี้ไปมุมมอง (CView*) พารามิเตอร์นี้จะใช้การใช้ "การแก้ไขภาพ" (หรือการเปิดใช้งานในสถาน) เท่านั้น สำหรับตอนนี้ คุณตั้งค่าพารามิเตอร์ที่เป็น NULL เนื่องจากคุณไม่ได้ใช้คุณลักษณะนี้ในเวลานี้?
เพื่อให้แน่ใจว่าเปิดใช้ว่า กรอบไม่เคยพยายามในตำแหน่งงาน คุณควรแทนCOleClientItem::CanActivateเป็นดังนี้
BOOL CRectItem::CanActivate()
{
nbsp ส่งกลับค่า FALSE
}
\oclient\rectitem.cpp(53): ข้อผิดพลาด C2065: 'GetBounds': undeclared ระบุ
\oclient\rectitem.cpp(53): ข้อผิดพลาด C2064: คำไม่ได้ประเมินไปยังฟังก์ชัน
\oclient\rectitem.cpp(84): ข้อผิดพลาด C2065: 'SetBounds': undeclared ระบุ
\oclient\rectitem.cpp(84): ข้อผิดพลาด C2064: คำไม่ได้ประเมินไปยังฟังก์ชัน(&N)
ใน MFC/OLE1, COleClientItem::GetBoundsและSetBoundsใช้สำหรับการสอบถาม และจัดการขอบเขตของสินค้า (สมาชิกด้านซ้ายและด้านบนถูกเสมอเป็นศูนย์) ใน 2 MFC/OLE นี้สามารถใช้เพิ่มเติมโดยตรงได้ โดยCOleClientItem::GetExtentและSetExtentซึ่งจัดการกับขนาดหรือCSizeแทน?
รหัสสำหรับ SetItemRectToServer ของคุณใหม่ และเรียก UpdateItemRectFromServer ที่มีลักษณะดังนี้:
BOOL CRectItem::UpdateItemRectFromServer()
{
nbsp ASSERT(m_bTrackServerSize)
ขนาด CSize
if (!GetExtent(&size))
ส่งกลับค่า FALSE / / ว่างเปล่า
/ / แมปจาก HIMETRIC กับพิกัดของหน้าจอ
{
CClientDC screenDC(NULL)
screenDC.SetMapMode(MM_HIMETRIC)
screenDC.LPtoDP(&size)
}
/ / เพียงตั้งค่าขนาดของสินค้า
ถ้า (m_rectSize() ! =ขนาด)
{
/ / โมฆะขนาด/ตำแหน่งเดิม
Invalidate()
m_rect.right = m_rect.left + size.cx
m_rect.bottom = m_rect.top + size.cy
/ / ตลอดจนใหม่ขนาด/ตำแหน่ง
Invalidate()
}
ส่งกลับ TRUE
}
BOOL CRectItem::SetItemRectToServer()
{
/ / การตั้งค่าขอบเขตอย่างเป็นทางการสำหรับรายการฝังตัว
ขนาด CSize = m_rectSize()
{
CClientDC screenDC(NULL)
screenDC.SetMapMode(MM_HIMETRIC)
screenDC.DPtoLP(&size)
}
ลอง
{
SetExtent(size) / / อาจทำให้การรอคอย
}
จุดอ่อน (CException, e)
{
ส่งกลับค่า FALSE / / การเชื่อมโยงจะไม่อนุญาตให้ SetBounds
}
END_CATCH
ส่งกลับ TRUE
}
\oclient\frame.cpp(50): ข้อผิดพลาด C2039: 'InWaitForRelease': ไม่ใช่สมาชิกของ 'COleClientItem'
\oclient\frame.cpp(50): ข้อผิดพลาด C2065: 'InWaitForRelease': undeclared ระบุ
\oclient\frame.cpp(50): ข้อผิดพลาด C2064: คำไม่ได้ประเมินไปยังฟังก์ชัน
ใน MFC/OLE1 แบบซิงโครนัส API เรียกจากที่บรรจุลงในเซิร์ฟเวอร์ถูกจำลองเนื่องจากถูก OLE1 inherently แบบอะซิงโครนัสในหลายกรณี ไม่จำเป็นต้องตรวจสอบการเรียกแบบอะซิงโครนัสค้างชำระในระหว่างดำเนินการก่อนที่จะประมวลผลคำสั่งจากผู้ใช้ MFC/OLE1 ให้ฟังก์ชันCOleClientItem::InWaitForReleaseสำหรับการทำเช่นนั้น ใน 2 MFC/OLE นี้ไม่จำเป็นต้อง ดังนั้นคุณสามารถลบการแทนของ OnCommand ใน CMainFrame ทั้งหมดเข้าด้วยกัน?
ณจุดนี้ จะรวบรวม และวิธีการเชื่อมโยง OCLIENT?
เปลี่ยนแปลงที่จำเป็นอื่น ๆ
มีบางสิ่งที่ทำไม่ได้ที่จะให้ OCLIENT ทำงาน อย่างไรก็ตาม ดีกว่าที่จะแก้ไขปัญหาเหล่านี้ขณะนี้แทนที่เป็นของรุ่นที่ใหม่กว่า?
ก่อนอื่น ก็จำเป็นในการเตรียมใช้งานไลบรารี OLE ทำได้ โดยการโทรAfxOleInitจากInitInstance:
if (!AfxOleInit())
{
AfxMessageBox ("ไม่สามารถเตรียมใช้งาน OLE ไลบรารี");
ส่งกลับค่า FALSE
}
ก็ยังควรตรวจสอบสำหรับฟังก์ชันเสมือนสำหรับการเปลี่ยนแปลงรายการพารามิเตอร์ ฟังก์ชันหนึ่งเช่นCOleClientItem::OnChangeแทนที่ในทุกโปรแกรมประยุกต์คอนเทนเนอร์ MFC/OLE ได้ ด้วยการดูที่วิธีใช้ออนไลน์ คุณจะเห็นได้ว่า ถูกเพิ่มเป็นพิเศษ 'DWORD dwParam' CRectItem::OnChange ใหม่มีลักษณะดังนี้
โมฆะ CRectItem::OnChange (OLE_NOTIFICATION wNotification, DWORD dwParam)
{
ถ้า (m_bTrackServerSize แอมป์ &
!UpdateItemRectFromServer())
{
/ / วัตถุที่ว่างเปล่า
ถ้า (wNotification == OLE_CLOSED)
{
/ / ไม่มีข้อมูลที่ได้รับสำหรับวัตถุ - ทำลาย
อ้าง (!IsVisible())
GetDocument() - > DeleteItem(this)
กลับ / / ไม่มีโปรแกรมปรับปรุง (สินค้าอยู่แล้วในขณะนี้)
}
}
ถ้า (wNotification ! = OLE_CLOSED)
Dirty()
Invalidate() / / ทำการเปลี่ยนใด ๆ จะทำให้เกิดใหม่เป็น
}
ใน MFC/OLE1 แอปพลิเคชันของคอนเทนเนอร์มาคลาสเอกสารจากCOleClientDoc ใน MFC/OLE 2 ชั้นนี้ถูกเอาออก และแทนที่ด้วยCOleDocument (องค์กรใหม่นี้ช่วยให้สร้างโปรแกรมประยุกต์คอนเทนเนอร์/เซิร์ฟเวอร์) มีการกำหนด#ที่แมปCOleClientDocไปที่COleDocumentเพื่อทำให้ง่ายขึ้น++:การสร้างพอร์ตของโปรแกรมประยุกต์ MFC/OLE1 MFC/OLE 2 เช่น OCLIENT หนึ่งในคุณลักษณะที่ไม่มาCOleDocumentที่ได้รับจากCOleClientDocเป็นคำสั่งมาตรฐานข้อความแผนผังรายการ สามารถทำได้เพื่อให้โปรแกรมเซิร์ฟเวอร์ ซึ่งยัง ใช้COleDocument (ทางอ้อม), ไม่กระทำกับค่าใช้จ่ายในที่ของตัวจัดการคำสั่งเหล่านี้ยกเว้นว่าพวกเขาเป็นโปรแกรมประยุกต์แบบคอนเทนเนอร์/เซิร์ฟเวอร์ ดังนั้น คุณต้องเพิ่มรายการต่อไปในการแมปข้อความ CMainDoc
ON_UPDATE_COMMAND_UI (ID_EDIT_PASTE, OnUpdatePasteMenu)
ON_UPDATE_COMMAND_UI (ID_EDIT_PASTE_LINK, OnUpdatePasteLinkMenu)
ON_UPDATE_COMMAND_UI (ID_OLE_EDIT_LINKS, OnUpdateEditLinksMenu)
ON_COMMAND (ID_OLE_EDIT_LINKS, COleDocument::OnEditLinks)
ON_UPDATE_COMMAND_UI (ID_OLE_VERB_FIRST, OnUpdateObjectVerbMenu)
ON_UPDATE_COMMAND_UI (ID_OLE_EDIT_CONVERT, OnUpdateObjectVerbMenu)
ON_COMMAND (ID_OLE_EDIT_CONVERT, OnEditConvert)
การใช้งานคำสั่งเหล่านี้ทั้งหมดอยู่ในCOleDocumentซึ่งเป็นคลาสพื้นฐานสำหรับเอกสารของคุณ?
ณจุดนี้ OCLIENT เป็นคอนเทนเนอร์โปรแกรมประยุกต์ OLE ทำงาน คุณจะสามารถแทรกสินค้าทุกชนิด (OLE1 หรือ OLE 2) เนื่องจากไม่มีการใช้งานรหัสจำเป็นในการเปิดใช้งานการเปิดใช้งานในสถาน มีแก้ไขรายการในหน้าต่างแยกต่างหากมากชอบ ด้วย OLE1 ส่วนถัดไปกล่าวถึงการเปลี่ยนแปลงที่จำเป็นเพื่อเปิดใช้งานการแก้ไขแบบแทนที่ (บางครั้งเรียก "การแก้ไข Visual")?
เพิ่ม "การแก้ไขภาพ"
หนึ่งในคุณลักษณะที่น่าสนใจมากที่สุดของ OLE ถูกเปิดใช้งานแบบแทนที่ (หรือ "แก้ไข Visual") คุณลักษณะนี้ช่วยให้เซิร์ฟเวอร์แอพลิเคชันเพื่อใช้ผ่านส่วนติดต่อผู้ใช้ของคอนเทนเนอร์ที่มีอินเทอร์เฟซการแก้ไขรื่นให้สำหรับผู้ใช้ การนำมาใช้ในสถานที่เปิดใช้งานการ OCLIENT ทรัพยากรบางพิเศษต้องเพิ่ม รวมทั้งรหัสเพิ่มเติมบางอย่าง ทรัพยากรเหล่านี้และรหัสได้ตามปกติโดย AppWizard ในความเป็นจริง รหัสที่นี่มากถูกยืมโดยตรงจากโปรแกรมประยุกต์ AppWizard สดกับ "Container" สนับสนุน?
ครั้งแรกของทั้งหมด เป็นความจำเป็นในการเพิ่มเมนูทรัพยากรที่จะใช้เมื่อมีรายการที่ใช้งานอยู่ในสถาน คุณสามารถสร้างทรัพยากรนี้เมนูพิเศษใน Visual c ++ โดยคัดลอกทรัพยากร IDR_OCLITYPE และเอาแต่ popups แฟ้มและหน้าต่างทั้งหมด แทรกแถบตัวแยกที่สองระหว่าง popups แฟ้มและหน้าต่างเพื่อบ่งชี้ระยะห่างของกลุ่ม (ควรมีลักษณะเช่น: แฟ้ม || หน้าต่าง) สำหรับข้อมูลเพิ่มเติมเกี่ยวกับสิ่งเหล่านี้ตัวคั่นหมายและวิธีผสานเมนู server และคอนเทนเนอร์ดู "เมนูและทรัพยากร:เมนูผสาน" ในOLE 2 ชั้น?
เมื่อคุณมีเมนูเหล่านี้สร้าง คุณจำเป็นต้องแจ้งให้ทราบรายละเอียดกรอบ สามารถทำได้ โดยการเรียกCDocTemplate::SetContainerInfoสำหรับแม่แบบเอกสารก่อนที่คุณเพิ่มลงในรายการแม่แบบเอกสารใน InitInstance ของคุณ รหัสใหม่เพื่อลงทะเบียนแม่แบบเอกสารที่มีลักษณะดังนี้
CDocTemplate * pTemplate =(CMultiDocTemplate ใหม่
nbsp IDR_OLECLITYPE
RUNTIME_CLASS(CMainDoc)
RUNTIME_CLASS(CMDIChildWnd), / / มาตรฐานเฟรมลูก MDI
RUNTIME_CLASS(CMainView))
pTemplate - > SetContainerInfo(IDR_OLECLITYPE_INPLACE)
AddDocTemplate(pTemplate)
IDR_OLECLITYPE_INPLACE ทรัพยากรคือ ทรัพยากรในสถานพิเศษที่สร้างขึ้นใน Visual c ++?
เมื่อต้องการเปิดใช้งานการเปิดใช้งานในสถาน มีบางสิ่งที่จำเป็นต้องเปลี่ยนแปลงในทั้งสองCView (CMainView) มาชั้นเช่นเดียวกับคลาCOleClientItemมา (CRectItem) เหล่านี้แทนที่ทั้งหมดโดย AppWizard และการใช้งานส่วนใหญ่จะมาโดยตรงจากโปรแกรมประยุกต์ที่ AppWizard เป็นค่าเริ่มต้น?
ในขั้นตอนแรกของพอร์ตนี้ การเปิดใช้งานแบบแทนที่ถูกปิดใช้งานทั้งหมด โดยแทนที่COleClientItem::CanActivate การแทนที่นี้ควรถูกเอาออกไปเพื่ออนุญาตให้มีการเปิดใช้งานในสถาน นอกจากนี้ NULL ถูกส่งผ่านไปทั้งหมดเรียกDoVerb (มีสองของพวกเขา) เนื่องจากให้มุมมองเท่านั้นไม่จำเป็นสำหรับการเปิดใช้งานในสถาน การเปิดใช้งานในสถานที่นำมาใช้อย่างเต็มรูปแบบ ก็จำเป็นต้องผ่านมุมมองถูกต้องในการเรียกDoVerb สายเหล่านี้อย่างหนึ่งคือในCMainView::OnInsertObject
pItem-gt; DoVerb(OLEIVERB_SHOW, this)(&G)
หนึ่งคือในCMainView::OnLButtonDblClk
m_pSelection-gt; DoVerb(OLEIVERB_PRIMARY, this)(&G)
ก็จำเป็นต้องแทนที่COleClientItem::OnGetItemPosition นี่บอกเซิร์ฟเวอร์จะย้ายหน้าต่างของสัมพันธ์กับหน้าต่างของคอนเทนเนอร์ที่เมื่อสินค้าถูกเปิดใช้งานในสถานที่ใด สำหรับ OCLIENT ใช้งานเป็นเรื่องขี้ปะติ๋ว
โมฆะ CRectItem::OnGetItemPosition (CRectamp; rPosition)
{
rPosition = m_rect
}(&A)
เซิร์ฟเวอร์ส่วนใหญ่ยังใช้สิ่งที่เรียกว่า "แบบแทนการปรับขนาด นี้ทำให้หน้าต่าง server จะมีขนาด และย้ายในขณะที่ผู้ใช้เป็นการแก้ไขสินค้า คอนเทนเนอร์ที่ต้องการมีส่วนร่วมในการกระทำนี้ เนื่องจากการเคลื่อนย้าย หรือปรับขนาดหน้าต่างมักจะมีผลต่อการตำแหน่งและขนาดต่าง ๆ ภายในคอนเทนเนอร์เอกสารเอง ใช้งานสำหรับ OCLIENT โดย m_rect ด้วยตำแหน่งใหม่และขนาดสี่เหลี่ยมภายในทำให้ตรงกัน?
BOOL CRectItem::OnChangeItemPosition(const CRectamp; rectPos)
{
ASSERT_VALID(this)
if (!COleClientItem::OnChangeItemPosition(rectPos))
ส่งกลับค่า FALSE
Invalidate()
m_rect = rectPos
Invalidate()
GetDocument() - > SetModifiedFlag()
ส่งกลับ TRUE
}
ณจุดนี้ มีรหัสเพียงพอเพื่อให้สินค้าที่จะ เปิดใช้งานในสถาน และจัดการกับการปรับขนาด และย้ายสินค้าเมื่อมีการใช้งาน แต่มีไม่มีรหัสที่จะอนุญาตให้ผู้ใช้ออกจากเซสชันการแก้ไข นั้น แม้ว่าบางเซิร์ฟเวอร์จะมีฟังก์ชันนี้เอง โดยการจัดการคีย์การหลบหนี มันจะแนะนำคอนเทนเนอร์มีสองวิธีในการยกเลิกใช้รายการ: (1) โดยคลิกที่ภายนอกสินค้า และ (2) โดยการกดปุ่มคีย์การหลบหนี?
สำหรับการหลบหนี การเร่ง ด้วย Visual c ++ที่แมปคีย์การ VK_ESCAPE ให้กับคำสั่ง เพิ่มคีย์ ID_CANCEL_EDIT จะถูกเพิ่มทรัพยากรคุณ ตัวจัดการสำหรับคำสั่งนี้เป็นไปตาม:
/ / ตัวจัดการคำสั่งต่อไปนี้ให้เป็นมาตรฐาน
/ / อินเทอร์เฟซผู้ใช้ยกเลิกแบบแทนที่แป้นพิมพ์
/ / แก้ไข session.void CMainView::OnCancelEdit()
{
nbsp / / ปิดรายการใช้งานอยู่สถานที่ในมุมมองนี้
COleClientItem * pActiveItem = GetDocument() - > GetInPlaceActiveItem(this)
ถ้า (pActiveItem ! = NULL)
pActiveItem - > Close()
ASSERT(GetDocument()-> GetInPlaceActiveItem(this) == NULL);
}
การจัดการกรณีที่ผู้ใช้คลินอกสินค้า คุณเพิ่มรหัสต่อไปนี้ในการเริ่มต้นของCMainView::SetSelection
ถ้า (pNewSel ! = m_pSelection || pNewSel == NULL)
{
nbsp COleClientItem * pActiveItem = GetDocument() - > GetInPlaceActiveItem(this)
ถ้า (pActiveItem ! = NULL & & pActiveItem ! = pNewSel)
pActiveItem - > Close()
}
& nbsp
เมื่อสินค้าถูกใช้งานอยู่ในสถาน ควรมีโฟกัส เพื่อให้แน่ใจว่า เป็นกรณีนี้ คุณจัดการ OnSetFocus เพื่อให้โฟกัสอยู่เสมอโอนไปยังกองสินค้าใช้งานอยู่เมื่อมุมมองของคุณได้รับโฟกัส:
/ / จำเป็นต้องมีการจัดการพิเศษของ OnSetFocus และ OnSize / / เมื่อวัตถุกำลังถูกแก้ไขในแทน
โมฆะ CMainView::OnSetFocus (CWnd * pOldWnd)
{
nbsp COleClientItem * pActiveItem = GetDocument() - > GetInPlaceActiveItem(this)
ถ้า (pActiveItem ! = NULL & &
pActiveItem - > GetItemState() == COleClientItem::activeUIState)
{
/ / ต้องการตั้งโฟกัสไปยังรายการนี้ถ้าเป็นมุมมองเดียวกัน
CWnd * pWnd = pActiveItem - > GetInPlaceWindow()
ถ้า (pWnd ! = NULL)
{
pWnd - > SetFocus() / / ไม่เรียกคลาสพื้นฐาน
กลับ
}
}
CView::OnSetFocus(pOldWnd)
}
เมื่อมุมมองที่ถูกปรับขนาด คุณจำเป็นต้องแจ้งให้ทราบถึงรายการใช้งานอยู่ที่มีการเปลี่ยนแปลงรูปวาดสี่เหลี่ยม การทำเช่นนี้คุณมีตัวจัดการสำหรับOnSize:
โมฆะ CMainView::OnSize (UINT nType, int cx, int cy)
{
nbsp CView::OnSize (nType, cx, cy);
COleClientItem * pActiveItem = GetDocument() - > GetInPlaceActiveItem(this)
ถ้า (pActiveItem ! = NULL)
pActiveItem - > SetItemRects()
}
กรณีศึกษา: HIERSVR จาก MFC 2.0
HIERSVRถูกรวมไว้ใน MFC 2.0 และใช้งาน OLE กับ MFC/OLE1 หมายเหตุนี้อธิบายถึงขั้นตอนต่าง ๆ ที่โปรแกรมประยุกต์นี้ถูกเริ่มต้นด้วยแปลงการใช้คลาสที่ 2 MFC/OLE สั้น ๆ มีเพิ่มจำนวนของคุณลักษณะหลังจากพอร์ตเริ่มต้นเสร็จสมบูรณ์ดี แสดงคลาสที่ 2 MFC/OLE คุณลักษณะเหล่านี้จะไม่สามารถครอบคลุมที่นี่ ดูตัวอย่างตัวเองสำหรับข้อมูลเพิ่มเติมเกี่ยวกับคุณลักษณะขั้นสูงเหล่านั้น?
หมายเหตุnbsp ข้อผิดพลาดในการคอมไพล์เลอร์และกระบวนการขั้นตอนถูกสร้างขึ้น ด้วย Visual c ++ 2.0 ข้อความแสดงข้อผิดพลาดเฉพาะและตำแหน่งที่ตั้งอาจมีการเปลี่ยนแปลงกับ Visual c ++ 4.0 แต่ยังคงข้อมูลแนวคิดที่ถูกต้อง(&N)?
การตั้ง และการเรียกใช้
วิธีการดำเนินการกับพอร์ต HIERSVR ตัวอย่างการ MFC/OLE คือ เริ่มต้น ด้วยการสร้าง และแก้ไขข้อผิดพลาดของคอมไพเลอร์ชัดเจนซึ่งจะส่งผลให้ ถ้าคุณใช้ตัวอย่าง HIERSVR จาก MFC 2.0 และคอมไพล์ภายใต้ MFC รุ่นนี้ คุณจะพบว่า มีไม่ผิดพลาดมากมายเพื่อแก้ไข (แม้ว่าจะมีมากกว่า ด้วยตัวอย่าง OCLIENT) ข้อผิดพลาดในใบสั่งที่มันจะเกิดขึ้นได้อธิบายไว้ด้านล่าง?
คอมไพล์และแก้ไขข้อผิดพลาด
\hiersvr\hiersvr.cpp(83): ข้อผิดพลาด C2039: 'RunEmbedded': ไม่ใช่สมาชิกของ 'COleTemplateServer'
ข้อผิดพลาดนี้แรกชี้ออกมากใหญ่ปัญหาด้วยฟังก์ชันInitInstanceสำหรับเซิร์ฟเวอร์ เตรียมใช้งานที่จำเป็นสำหรับเซิร์ฟเวอร์ OLE ได้คงการเปลี่ยนแปลงที่ใหญ่ที่สุดที่คุณจะต้องทำการโปรแกรมประยุกต์ของคุณ MFC/OLE1 เพื่อให้มันทำงานอย่างใดอย่างหนึ่ง สิ่งดีที่สุดทำอย่างไรจะดูอะไรที่ AppWizard สร้างสำหรับเซิร์ฟเวอร์ OLE และปรับเปลี่ยนรหัสของคุณได้ตามความเหมาะสม นี่คือบางจุดเพื่อระลึกถึง:
ความจำเป็นในการเตรียมใช้งานไลบรารี OLE โดยการเรียกAfxOleInit
เรียกใช้ SetServerInfo บนวัตถุแม่แบบเอกสารเพื่อตั้งค่าเซิร์ฟเวอร์ทรัพยากรจับและ runtime ชั้นข้อมูลที่คุณไม่สามารถตั้งค่าได้ ด้วยการกำหนดCDocTemplate?
ไม่ต้องแสดงหน้าต่างหลักของโปรแกรมประยุกต์ของคุณถ้า /Embedding อยู่บนบรรทัดคำสั่ง?
คุณจำเป็นต้องGUIDสำหรับเอกสารของคุณ นี้เป็นตัวระบุที่ไม่ซ้ำกันสำหรับชนิดของเอกสาร (128 บิต) AppWizard จะสร้างให้คุณ ดังนั้นถ้าคุณใช้เทคนิคอธิบายไว้ที่นี่การคัดลอกรหัสใหม่จากเซิร์ฟเวอร์โปรแกรมประยุกต์ AppWizard ที่สร้างขึ้นใหม่ คุณสามารถเพียงแค่ "ขโมย" GUID จากโปรแกรมประยุกต์นั้น ถ้า ไม่ คุณสามารถใช้ GUIDGENโปรแกรมอรรถประโยชน์ EXE ในไดเรกทอรีของช่องเก็บ?
จำเป็นต้อง "เชื่อมต่อ" วัตถุของคุณCOleTemplateServerลงในแม่แบบเอกสาร โดยการเรียกCOleTemplateServer::ConnectTemplate?
ปรับปรุงรีจิสทรีของระบบเมื่อโปรแกรมประยุกต์ของคุณมีการเรียกใช้แบบสแตนด์อโลน วิธีนี้ ถ้าผู้ใช้ย้ายEXE สำหรับโปรแกรมประยุกต์ของคุณ ทำงานจากตำแหน่งที่ตั้งใหม่จะปรับปรุงฐานข้อมูลการลงทะเบียนระบบ Windows ให้ชี้ไปที่ตำแหน่งใหม่?
หลังจากการใช้ทั้งหมดของการเปลี่ยนแปลงเหล่านี้ยึดตามสิ่งที่ AppWizard สร้างสำหรับInitInstance, InitInstance (และเกี่ยวข้อง GUID) สำหรับ HIERSVR ควรอ่านเป็นดังนี้:
// this is the GUID for HIERSVR documents
static const GUID BASED_CODE clsid =
{ 0xA0A16360L, 0xC19B, 0x101A, { 0x8C, 0xE5, 0x00, 0xDD, 0x01, 0x11, 0x3F, 0x12 } };
/////////////////////////////////////////////////////////////////////////////
// COLEServerApp initialization
BOOL COLEServerApp::InitInstance()
{
// OLE 2 initialization
if (!AfxOleInit())
{
AfxMessageBox("Initialization of the OLE failed!");
return FALSE;
}
// Standard initialization
LoadStdProfileSettings(); // Load standard INI file options
// Register document templates
CDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(IDR_HIERSVRTYPE,
RUNTIME_CLASS(CServerDoc),
RUNTIME_CLASS(CMDIChildWnd),
RUNTIME_CLASS(CServerView));
pDocTemplate->SetServerInfo(IDR_HIERSVRTYPE_SRVR_EMB);
AddDocTemplate(pDocTemplate);
// create main MDI Frame window
CMainFrame* pMainFrame = new CMainFrame;
if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
return FALSE;
m_pMainWnd = pMainFrame;
SetDialogBkColor(); // gray look
// enable file manager drag/drop and DDE Execute open
m_pMainWnd->DragAcceptFiles();
EnableShellOpen();
m_server.ConnectTemplate(clsid, pDocTemplate, FALSE);
COleTemplateServer::RegisterAll();
// try to launch as an OLE server
if (RunEmbedded())
{
// "short-circuit" initialization -- run as server!
return TRUE;
}
m_server.UpdateRegistry();
RegisterShellFileTypes();
// not run as OLE server, so show the main window
if (m_lpCmdLine[0] == '\0')
{
// create a new (empty) document
OnFileNew();
}
else
{
// open an existing document
OpenDocumentFile(m_lpCmdLine);
}
pMainFrame->ShowWindow(m_nCmdShow);
pMainFrame->UpdateWindow();
return TRUE;
}
คุณจะสังเกตเห็นว่า รหัสข้างต้นหมายถึงทรัพยากร ID ใหม่ IDR_HIERSVRTYPE_SRVR_EMB นี่คือทรัพยากรที่จะใช้เมื่อมีแก้ไขเอกสารที่ถูกฝังในคอนเทนเนอร์อีกเมนู ใน MFC/OLE1 รายการเมนูเฉพาะเมื่อต้องการแก้ไขรายการฝังตัวถูกปรับเปลี่ยนบนตัวแมลงวัน ใช้เป็นโครงสร้างเมนูที่แตกต่างกันทั้งหมดเมื่อแก้ไขรายการฝังตัวแทนของการแก้ไขเอกสารที่ใช้แฟ้มทำให้ง่ายขึ้นมากเพื่อให้มีอินเทอร์เฟซผู้ใช้ที่แตกต่างกันสำหรับโหมดแยกต่างหากสองเหล่านี้ คุณจะเห็นในภายหลัง ทรัพยากรเมนูทั้งหมดแยกต่างหากจะใช้เมื่อทำการแก้ไขวัตถุฝังตัวแบบแทนที่?
การสร้างทรัพยากรนี้ โหลดทรัพยากรสคริปต์ลงใน Visual c ++ และคัดลอกทรัพยากร IDR_HIERSVRTYPE เมนูที่มีอยู่ การเปลี่ยนชื่อทรัพยากรใหม่ IDR_HIERSVRTYPE_SRVR_EMB (เป็นแบบแผนการตั้งชื่อเดียวกันที่ใช้ AppWizard) ถัดไป เปลี่ยน "แฟ้มบันทึก" การ "ปรับปรุงแฟ้ม" ให้สั่ง ID ID_FILE_UPDATE ยัง เปลี่ยน "แฟ้มบันทึกเป็น" "แฟ้มบันทึกสำเนาเป็น" ให้สั่ง ID ID_FILE_SAVE_COPY_AS กรอบแสดงการใช้งานคำสั่งเหล่านี้ทั้งสอง?
\hiersvr\svritem.h(60): ข้อผิดพลาด C2433: 'OLESTATUS': 'เสมือน' ไม่ได้รับอนุญาตบนข้อมูลประกาศ
\hiersvr\svritem.h(60): ข้อผิดพลาด C2501: 'OLESTATUS': decl-specifiers ที่ขาดหายไป
\hiersvr\svritem.h(60): ข้อผิดพลาด C2146: ข้อผิดพลาดไวยากรณ์: หายไป ก่อนที่ จะระบุ 'OnSetData'
\hiersvr\svritem.h(60): ข้อผิดพลาด C2061: ข้อผิดพลาดไวยากรณ์: ตัวระบุ 'OLECLIPFORMAT'
\hiersvr\svritem.h(60): ข้อผิดพลาด C2501: 'OnSetData': decl-specifiers ที่ขาดหายไป
มีข้อผิดพลาดที่เกิดจากการแทนของOnSetDataเนื่องจากมันถูกอ้างอิงถึงชนิดOLESTATUSจำนวนหนึ่ง OLESTATUSวิธีการ OLE1 ส่งกลับข้อผิดพลาดได้ นี้มีการเปลี่ยนแปลงการhresult ในใน OLE 2 ถึงแม้ว่า MFC แปลงhresult ในมักจะเป็นCOleExceptionที่ประกอบด้วยข้อผิดพลาด ในกรณีนี้เฉพาะ การแทนที่ของOnSetDataไม่จำเป็น ดังนั้นสิ่งที่ง่ายที่สุดที่จะทำคือการ เอาออก?
\hiersvr\svritem.cpp(30): ข้อผิดพลาด C2660: 'COleServerItem::COleServerItem': ฟังก์ชันไม่มีพารามิเตอร์ 1
พารามิเตอร์COleServerItemที่ใช้พารามิเตอร์ 'BOOL' เป็นพิเศษ ธงนี้กำหนดวิธีการจัดการหน่วยความจำจะทำบนวัตถุCOleServerItem ด้วยการตั้งค่าเป็น TRUE กรอบงานจัดการการจัดการหน่วยความจำของวัตถุเหล่านี้ ลบออกเมื่อพวกเขาไม่จำเป็นต้อง HIERSVR ใช้วัตถุCServerItem (มาจากCOleServerItem) เป็นส่วนหนึ่งของข้อมูลท้องถิ่น ดังนั้นคุณสามารถกำหนดค่าสถานะนี้เป็น FALSE ซึ่งช่วยให้ HIERSVR ที่กำหนดเมื่อมีลบสินค้าแต่ละเซิร์ฟเวอร์?
\hiersvr\svritem.cpp(44): ข้อผิดพลาด C2259: 'CServerItem': ความพยายามที่ไม่ถูกต้องเมื่อต้องการสร้างอินสแตนซ์ของคลาสนามธรรม
\hiersvr\svritem.cpp(44): ข้อผิดพลาด C2259: 'CServerItem': ความพยายามที่ไม่ถูกต้องเมื่อต้องการสร้างอินสแตนซ์ของคลาสนามธรรม
ตามนัยข้อผิดพลาดเหล่านี้ มีฟังก์ชันบางฟังก์ชัน 'บริสุทธิ์เสมือน' ซึ่งไม่มีการแทนใน CServerItem ส่วนใหญ่นี้เกิดจากข้อเท็จจริงที่มีการเปลี่ยนแปลงรายการพารามิเตอร์ของ OnDraw เมื่อต้องการแก้ไขข้อผิดพลาดนี้ เปลี่ยนCServerItem::OnDrawเป็นดังนี้ (รวมทั้งการประกาศใน svritem.h)
BOOL CServerItem::OnDraw(CDC* pDC, CSizeamp; rSize)
{
/ / ทำการร้องขอจาก OLE วาดโหน
pDC - > SetMapMode(MM_TEXT) / / เสมอ ในพิกเซล
กลับ DoDraw (pDC, CPoint(0,0), FALSE);
}
พารามิเตอร์ใหม่คือ 'rSize' นี้ช่วยให้คุณสามารถกรอกข้อมูลในขนาดของรูปวาด ถ้าสะดวก ขนาดนี้ต้องอยู่ในHIMETRICกัน ในกรณีนี้ จะไม่สะดวกในการกรอกข้อมูลค่านี้ใน ดังนั้นกรอบเรียกOnGetExtentเพื่อดึงขอบเขต ที่ทำงาน คุณจะต้องใช้OnGetExtent:
BOOL CServerItem::OnGetExtent(DVASPECT dwDrawAspect, CSizeamp; rSize)
{
ถ้า (dwDrawAspect ! = DVASPECT_CONTENT)
กลับ COleServerItem::OnGetExtent (dwDrawAspect, rSize);
rSize = CalcNodeSize()
ส่งกลับ TRUE
}
\hiersvr\svritem.cpp(104): ข้อผิดพลาด C2065: 'm_rectBounds': undeclared ระบุ
\hiersvr\svritem.cpp(104): ข้อผิดพลาด C2228: ด้านซ้ายของ 'SetRect' ต้องมี คลา/struct/สหภาพ ชนิด
\hiersvr\svritem.cpp(106): ข้อผิดพลาด C2664: ' โมฆะ __pascal __far DPtoLP (struct:: tagPOINT __far *, int) __far const ': ไม่สามารถแปลงพารามิเตอร์ 1 จาก ' int __far *' กับ ' struct:: tagPOINT __far *'(&A)
ใน CServerItem::CalcNodeSize ฟังก์ชันขนาดของสินค้าถูกแปลงเป็นHIMETRICและเก็บไว้ในm_rectBounds ไม่มีสมาชิกของCOleServerItemอย่างชาญฉลาด 'm_rectBounds' (มันมาบางส่วนแทนm_sizeExtentแต่ใน OLE 2 สมาชิกนี้มีการใช้งานที่แตกต่างกันเล็กน้อยกว่าm_rectBoundsได้ใน OLE1) ตั้งค่าขนาดHIMETRICเข้าไปในตัวแปรนี้สมาชิก คุณจะกลับก็ ค่าที่ส่งคืนนี้ถูกใช้ในOnGetExtentการใช้งานก่อนหน้านี้?
CSize CServerItem::CalcNodeSize()
{
nbsp CClientDC dcScreen(NULL)
m_sizeNode = dcScreen.GetTextExtent (m_strDescription
m_strDescription.GetLength())
m_sizeNode += CSize (CX_INSET * 2, CY_INSET * 2);
/ / การตั้งค่าที่แนะนำ HIMETRIC ขนาด
CSize ขนาด (m_sizeNode.cx, m_sizeNode.cy);
dcScreen.SetMapMode(MM_HIMETRIC)
dcScreen.DPtoLP(&size)
ส่งกลับค่าขนาด
}
นอกจากนี้ CServerItem ยังแทนCOleServerItem::OnGetTextData ฟังก์ชันนี้ล้าสมัยใน MFC/OLE และถูกแทนที่ โดยกลไกที่แตกต่างกัน ตัว MFC OLE อย่างรุ่น MFC 3.0 HIERSVRใช้ฟังก์ชันนี้ โดยการแทนที่COleServerItem::OnRenderFileData ฟังก์ชันนี้ไม่สำคัญสำหรับพอร์ตนี้พื้นฐาน ดังนั้นคุณสามารถลบการแทน OnGetTextData?
มีหลายอย่างเพิ่มเติมผิดใน svritem.cpp ที่ยังไม่ถูกส่งถึงกัน เหล่านั้นไม่ใช่ข้อผิดพลาด "จริง" เพียงข้อผิดพลาดที่เกิดจากข้อผิดพลาดก่อนหน้านี้?
\hiersvr\svrview.cpp(325): ข้อผิดพลาด C2660: 'CopyToClipboard': ฟังก์ชันไม่มีพารามิเตอร์ที่ 2
COleServerItem::CopyToClipboardไม่สนับสนุนค่าสถานะ 'bIncludeNative' ข้อมูลดั้งเดิม (ข้อมูลที่เขียนตามฟังก์ชั่น Serialize ของสินค้าเซิร์ฟเวอร์) ถูกคัดลอกเสมอมา ดังนั้นคุณลบพารามิเตอร์แรก นอกจากนี้CopyToClipboardจะโยนข้อยกเว้นเมื่อมีข้อผิดพลาดเกิดขึ้นแทนที่ของส่งกลับ FALSE เปลี่ยนรหัสสำหรับ CServerView::OnEditCopy เป็นดังนี้
โมฆะ CServerView::OnEditCopy()
{
nbsp ถ้า (m_pSelectedNode == NULL)
AfxThrowNotSupportedException()
ลอง
{
m_pSelectedNode - > CopyToClipboard(TRUE)
}
CATCH_ALL(e)
{
AfxMessageBox ("คัดลอกไปที่คลิปบอร์ดล้มเหลว");
}
END_CATCH_ALL }
แม้ว่ามีข้อผิดพลาดเพิ่มเติมที่เป็นผลมาจากการคอมไพล์ของรุ่น MFC 2.0 HIERSVR กว่าที่มีสำหรับ OCLIENT รุ่นเดียวกัน ไม่มีน้อยลงจริง ๆ การเปลี่ยนแปลง?
ณจุดนี้ HIERSVR จะคอมไพล์ และการเชื่อมโยง และทำงาน เป็นเซิร์ฟเวอร์ OLE แต่ ไม่สถานที่แก้ไข คุณลักษณะ ซึ่งจะนำมาใช้ถัดไป?
เพิ่ม "การแก้ไขภาพ"
เพิ่ม "การแก้ไขภาพ" (หรือการเปิดใช้งานในสถาน) ไปยังโปรแกรมประยุกต์เซิร์ฟเวอร์นี้ มีเพียงไม่กี่สิ่งคุณต้องดูแล:
ง่ายต่อการสร้างทรัพยากรเมนูได้ เรียกใช้งาน Visual c ++ คัดลอกทรัพยากรเมนู IDR_HIERSVRTYPE ให้กับทรัพยากรของเมนูที่เรียกว่า IDR_HIERSVRTYPE_SRVR_IP ปรับเปลี่ยนเมนูเพื่อให้อยู่ชิดซ้ายเท่านั้นแก้ไขและวิธีใช้เมนู popups เพิ่มตัวคั่นที่สองให้กับเมนูในระหว่างเมนูวิธีใช้และการแก้ไข (ควรมีลักษณะเช่น: แก้ไข || วิธีใช้) ดูข้อมูลเพิ่มเติมในสิ่งเหล่านี้ตัวคั่นหมายและวิธีผสานเมนู server และคอนเทนเนอร์ "เมนูและทรัพยากร:เมนูผสาน" ในOLE 2 ชั้น?
บิตแมปสำหรับแถบเครื่องมือของเซตย่อยสามารถสร้างได้ง่ายขึ้น โดยการคัดลอกมาจากโปรแกรมประยุกต์สร้าง AppWizard แบบสดด้วยตัวเลือก "Server" ในการตรวจสอบ บิตแมปนี้แล้วสามารถถูกนำเข้าลงใน Visual c ++ ต้องแน่ใจว่าการให้บิตแมปที่มี ID ของ IDR_HIERSVRTYPE_SRVR_IP?
เรียนมาจากCOleIPFrameWndสามารถคัดลอกจากโปรแกรมประยุกต์ AppWizard ที่สร้างขึ้นด้วยการสนับสนุนของเซิร์ฟเวอร์ด้วย คัดลอกไฟล์ทั้งสอง IPFRAMECPP และ IPFRAMEH และเพิ่มลงในโครงการ ตรวจสอบให้แน่ใจว่า การโทรLoadBitmapถึง IDR_HIERSVRTYPE_SRVR_IP บิตแมปที่สร้างขึ้นในขั้นตอนก่อนหน้า?
ขณะที่ทรัพยากรใหม่และชั้นเรียนทั้งหมดถูกสร้างขึ้น เพิ่มรหัสที่จำเป็นเพื่อให้รู้เกี่ยวกับกรอบ (และรู้ว่า โปรแกรมประยุกต์นี้ขณะนี้สนับสนุนการแก้ไขแบบแทน) ทำได้ โดยการเพิ่มพารามิเตอร์บางอย่างเพิ่มเติมเพื่อSetServerInfoการโทรในฟังก์ชันInitInstance:
pDocTemplate-gtSetServerInfo (IDR_HIERSVRTYPE_SRVR_EMB
IDR_HIERSVRTYPE_SRVR_IP, RUNTIME_CLASS(CInPlaceFrame))(&G)
เป็นตอนนี้พร้อมที่จะเรียกใช้ในสถานในคอนเทนเนอร์ใด ๆ ซึ่งยัง สนับสนุนการเปิดใช้งานในตำแหน่งนั้น แต่ มีข้อบกพร่องเล็กน้อยหนึ่งยังคง lurking ในรหัส HIERSVR สนับสนุนบริบทเมนู แสดงเมื่อผู้ใช้กดปุ่มเมาส์ด้านขวา เมนูนี้ทำงานเมื่อ HIERSVR เปิดเต็ม แต่ไม่ทำงานเมื่อแก้ไขฝังแบบแทนที่ เหตุผลสามารถยึดหมุดลงไปนี้บรรทัดเดียวของรหัสใน CServerView::OnRButtonDown
pMenu-gtTrackPopupMenu(TPM_CENTERALIGN | TPM_RIGHTBUTTON
point.x, point.y, AfxGetApp() - > m_pMainWnd)
สังเกตการอ้างอิงไป() AfxGetApp-gt; m_pMainWnd เมื่อเซิร์ฟเวอร์ การเปิดใช้งานในสถาน มีหน้าต่างหลัก และ m_pMainWnd ถูกตั้งค่า แต่ก็มักจะมองไม่เห็น นอกจากนี้ หน้าต่างนี้อ้างอิงถึงหน้าต่างหลักของโปรแกรมประยุกต์ MDI กรอบหน้าต่างที่ปรากฏเมื่อเซิร์ฟเวอร์อย่างเต็มรูปแบบเปิด หรือเรียกใช้แบบสแตนด์อโลน ไม่ได้อ้างอิงไปยังหน้าต่างเฟรมที่ใช้งานอยู่ ซึ่งเมื่อสถานที่ทำงานเป็นหน้าต่างเฟรมมาจากCOleIPFrameWnd เพื่อเรียกหน้าต่างที่ใช้งานถูกต้องแม้ว่าแบบแทนการแก้ไข MFC รุ่นนี้เพิ่มฟังก์ชันใหม่AfxGetMainWnd โดยทั่วไปแล้ว คุณควรใช้ฟังก์ชันนี้แทนAfxGetApp() - > m_pMainWnd รหัสนี้ต้องเปลี่ยนเป็นดังนี้:
pMenu-gtTrackPopupMenu(TPM_CENTERALIGN | TPM_RIGHTBUTTON
point.x, point.y, AfxGetMainWnd(&))
ขณะนี้ คุณมีเซิร์ฟเวอร์ OLE minimally เปิดใช้สำหรับการเปิดใช้งานในสถานที่ทำงาน แต่ไม่มียังคุณลักษณะต่าง ๆ 2 MFC/OLE ที่ไม่พร้อมใช้งานใน MFC/OLE1 ดูตัวอย่าง HIERSVR สำหรับข้อคิดเห็นเพิ่มเติมเกี่ยวกับคุณลักษณะต่าง ๆ ที่คุณอาจต้องการใช้ บางคุณลักษณะ HIERSVR ใช้อยู่ด้านล่าง:
ตัวอย่าง HIERSVR ใน MFC 3.0 ยังใช้การออกแบบที่แตกต่างกันเล็กน้อยสำหรับสินค้าของเซิร์ฟเวอร์ นี้ช่วยประหยัดหน่วยความจำ และทำให้การเชื่อมโยงของคุณมีความยืดหยุ่น กับ HIERSVR รุ่น 2.0 แต่ละโหนดในทรีเป็น-a COleServerItem COleServerItemดำเนินตามค่าใช้จ่ายเพิ่มเติมบิตในมากกว่าที่จำเป็นสำหรับแต่ละโหนเหล่านี้อย่างเคร่งครัด แต่COleServerItemจำเป็นสำหรับแต่ละการเชื่อมโยงที่ใช้งานอยู่ แต่สำหรับส่วนใหญ่ มีการเชื่อมโยงที่ใช้งานน้อยมากเวลาที่กำหนด เมื่อต้องการทำสิ่งนี้ให้มีประสิทธิภาพมากขึ้น การ HIERSVR ของ MFC รุ่นนี้แยกโหนดจากCOleServerItem มีทั้งแบบ CServerNode และคลาCServerItem CServerItem (มาจากCOleServerItem) ถูกสร้างเมื่อจำเป็นเท่านั้น เมื่อคอนเทนเนอร์ (หรือคอนเทนเนอร์) หยุดใช้เฉพาะที่การเชื่อมโยงไปที่โหนเฉพาะ CServerItem วัตถุที่เชื่อมโยงกับ CServerNode จะถูกลบ การออกแบบนี้คือมีความยืดหยุ่น และมีประสิทธิภาพมากขึ้น ความยืดหยุ่นของมาในเมื่อทำงานกับหลายการเชื่อมโยงการเลือก HIERSVR รุ่นสองเหล่านี้ไม่สนับสนุนการเลือกหลาย แต่มันจะง่ายขึ้นมากเมื่อต้อง การเพิ่ม (และ เพื่อสนับสนุนการเชื่อมโยงให้เลือกเช่น) กับ HIERSVR เนื่องจากCOleServerItemถูกแยกจากข้อมูลท้องถิ่นรุ่น MFC 3.0?
หมายเหตุด้านเทคนิคตามหมายเลข|nbsp หมายเหตุด้านเทคนิคตามประเภท(&N)