主页  |  产品  | 我们的客户 | 技术支持 | 下载 | 购买   
UCanCode.com一起释放Visual C++的巨大能量!
 
E-Form++可视化图形组件库企业版本
(100% VC++, VB, C#源代码)
 产品特点 
电子表单解决方案源码
电力系统解决方案源码
报表打印解决方案源码
工作流程图解决方案源码
煤炭行业解决方案源码
仪器仪表解决方案源码
可变打印解决方案源码
图形建模解决方案源码
GIS制图解决方案源码
Visio制图解决方案源码
工业控制解决方案源码
BPM业务流程图解决 方案源码
工业监控解决方案源码
流程图与控制流源源码
组织关系图源码
图形编辑器源码
UML制图编辑器源码
地 图演示方案源码
CAD设计控件源码
建筑平面制图源码
价格查询
免费下载
  现在购买
UCCDraw可视化图形控件
(支持Java, Delphi, C#等开发环境)
  软件特点
  价格查询
  免费下载
  现在购买
E-Form++ 流程图与电子表单组件库专业版
  软件特点
  价格查询
  免费下载
  现在购买
Form++ 流程图源码组件库专业版
  软件特点
  价格查询
免费下载
现在购买
DocBuilder
  软件特点
  范例
技术支持
  软件注册
  在线升级
  在线文档
  开发课程
  开发范例
  开发知识库
  软件Bug报告
  改进建议
友情连接
 联络我们


在这里您可以了解UCanCode.NET的威力.

  开发知识库

Form++开发知识库
 

我们的知识库使用精炼的语言来解决常见的问题。虽然无法与一些大公司的知识库相比,我们会尽力提供更多的信息。知识库将不断更新,增加新的内容。所以希望大家经常关注。

我们的技术支持团队将不断更新和扩充知识库,从一般的编程问题到完整的实例。您可以通过编目、产品类型、或者目录索引来找到您所需的信息。要获取这些信息,您无需注册。

其中的文章回答了很多的用户最常提出的问题。通常情况下,这些文章可以说是超越了版本限制的。您可以类推到你所遇到的情况。

这个页面包含常见的问题和我们的技术支持小组的解答,以及一些常用技巧和提示。
注意:在以下的解答中我们将按如下的简记惯例来描述用户界面操作。组合键按以下方式如:Ctrl+Alt+Delete,意思是你同时按下Control键、Alt键和Delete键不放。菜单的选择将如下描述:File->Open,意思是你打开文件(File)菜单,然后选择打开(Open )项。

问题列表:


Q: 我已经安装了Form++,但是我找不到任何DLL或者库(lib)文件,在那里去找?
A:
你需要编译所有的Form++ 类库中的 DLL lib文件。从开始菜单->程序->Form++ Library找到类库。你必须为你的平台生成调试(build)和发行(releease)两种版本。

FOENGD40.dll FOENGD40.lib DLL - Win32 Debug
FOENG40.dll FOENG40.lib DLL - Win32 Release
FOStatic40D.lib Static Library - Win32 Debug
FOStatic40.lib Static Library - Win32 Release

注意:如果您使用的是评估版,将只有静态连接库---Win32调试版动态连接文件。您不必生成库。

Back to Top

Q:开始使用Form++之前,我要做些什么,我怎样设定我的VisualStudio®?
A:
VisualStudio你必须作以下调整。假设你将Form++ Library 安装在"C:\Program Files\UCanCode Software Inc\Form++ Library V2.0"F目录下。如果你将Form++安装到其他目录下,你需要作一些调整。

  1. 选择"Tools"菜单中的"Options"然后选中"Directories".
  2. 设定"Show directories for:""Include files".
  3. 增加"C:\Program Files\UCanCode Software Inc\Form++ Library V2.0\Fo20\Include" to the?/font>
  4. 设定"Show directories for:""Library files".
  5. 增加"C:\Program Files\UCanCode Software Inc\Form++ Library V2.0\Lib" to the到列表中 list.
  6. 设定"Show directories for:""Source files".
  7. 增加"C:\Program Files\UCanCode Software Inc\Form++ Library V2.0\Fo20\source" to the
  8. 增加"C:\Program Files\UCanCode Software Inc\Form++ Library V2.0\Fo20\Include" to the list.
  9.  现在可以从view菜单选中resource include 项增加Form++的资源到你的程序中,

    在只读目录框中,在最后一行输入以下一行:

    #include "fores.h" 

    Compile-time编译目录框中,输入下面一行:

    #include "fores.rc" 

    单击OK按钮。 会出现一个警告,在按OK 按钮。

你下载和安装Form++类库后,打开工程工作区(见上面的问题,如果是评估版,这是不可用的)。依赖于工作平台,建立调试和发行两种版本的库文件。之后,你打开AppWizard的工作区,编译工程。现在你可以象使用标准的AppWizard产生MFC工程一样使用类向导。做个例子看看工程是什么样。

Back to Top

Q: 怎样使我的程序支持Ole 拖放功能?
A:
要让你的程序支持Ole拖放功能,你必须加入如下代码:

BOOL CCustomSampleApp::InitInstance()

AfxOleInit();

Q: 我怎样使用上Form++资源库?
A:
要在你已有的应用中加入Form++资源,你要在你的stdafx.h文件中加入以下一行,首先你必须在DevStudio的搜索目录下增加了.\lib, .\bin.\include
目录,且与你安装form++的目录一致。

#include <FO.H> // Form++ Library MFC extensions

Back to Top

Q:  want to prevent resizing of an image but make sure I don't want to lock
the control otherwise I won't be able to move the image. Is there any
function thought which I can enable and disable the control/image resizing?

A: You can use the following method to do it:
void LockWidthAndHeight(const BOOL bLock) it defined in class CFODrawShape

Back to Top

Q: 贵公司在在线帮助中使用复制Basic Shapes.trsForms Shapes.trsindex.dat3个文件到应用程序中的办法来增加组建,试问我自己能编制该文件来增加我自己需要的图形组件吗?如果能,我该怎么做?

A: 如果您自己增加的组件,需要做两个方面的工作:
1
、通过ToolBox来添加新的组件页,并选择另存为菜单保存为新的trs文件,需要同原来的Basic Shapes.trs放置在同一个目录下面。例如:MyShape.trs

2
、需要修改index.dat文件,添加:
3#MyShape.trs
这样在您下一次运行程序的时候,您自己的图形组件页就产生了。

Back to Top

Q: 如何使用单位转换功能?

A: 关于单位转换的类名称为:CFOScaleUint,在新的在线帮助系统中的 <产品介绍>专题中专门有 <单位换算>一节介绍。

Back to Top

Q: 如何在Form++中增加新的命令?

A: 如示例程序所示.

Back to Top

Q: 利用Form++如何生成一个可以旋转任意角度的自定义复合对象?
我发现提供的例子中Basic Shpes中的复合对象可以任意旋转,可是自定义的就不行。
我自定义的过程如下:
画出复合对象,选中并保存为sid文件,建立trs文件,新建对象,装载对象数据(from .sid)
然后拖动此对象到工作区域,可是此对象不能任意旋转。

A: 如果您希望您开发的对象需要旋转属性,您需要在自定义组件的构造函数中调用下面这个函数:
SetOver4ResizeHandles(TRUE);
可以参考示例CustomMSample中的CMyCorsssLineShape类的定义。

Back to Top

Q: Can U give me a function where I'll pass CFOImageShape pointer and it'll make a list of all links only. Make sure that I won't use GetFormObject() function.

A: Try the following code:

CFODrawShapeList listAllLink;
 if(pObj->IsKindOf(RUNTIME_CLASS(CFOImageShape)))
 {
  CFOImageShape *pComp = (CFOImageShape *)pObj;
  POSITION posport = pComp->GetCompList()->GetHeadPosition();
  CFOPortShape *pPort = NULL;
  while(posport != NULL)
  {
   pPort = (CFOPortShape* )pComp->GetCompList()->GetNext(posport);
   CFODrawShapeList *pLinkList = pPort->GetCompList();
   POSITION poslist = pLinkList->GetHeadPosition();
   while(poslist != NULL)
   {
    listAllLink.AddTail((CFOLinkShape *)pLinkList->GetNext(poslist));
   }
  }
 }

Back to Top

Q: 如何让我的应用程序静态连接到Form++?

A: stdafx.h#include "fo.h"之前添加下面一行代码:

#define _DIAGRAM_STATIC_
#include <FO.H> // Form++ Library MFC extensions

Back to Top

我们将随时增加新的内容!

Q: 如何在Form++中增加新的组件?

A: 下面是增加新组件的基本步骤:

1、您需要利用Form++ Class AddIn程序,从CFODrawPortsShape或者CFODrawShape继承一个新的组件类,例如:CMyComp;

2、为此组件指定一个ID值。

3、在您当前应用程序的Data Model类中修改创建组件代码来创建新的组件。

4、在MyComp代码文件中重载组件绘制代码以及其他控制代码。

 可以参考示例程序CustomMSample以及用户在线文档中相应的描述。

Back to Top

Q:我用Form++ Class AddIn增加的新的类不能在Visual C++ClassWizard显示出来?

A: To update this change to your project classes, you will need to go to your project folder, find the .clw file and delete it. Then go back to Visual Studio and load the Class Wizard. Visual Studio will then give you an error message and ask you to create a new Class Wizard database. Simply choose the default and you will be able to see all the three new classes in your Class Wizard.

Back to Top

Q:我使用Form++ Class AddIn增加了新的组件类CMyShape,但是我如何才能够判断我当前选择的对象列表中是否包含此组件?

A:您需要调用下面的代码来实现:

CFODrawShape *pObj = GetCurrentSelectShape();
if(pObj != NULL)
{
  if(pObj->IsKindOf(RUNTIME_CLASS(CMyShape)))
  {
    CMyShape *pShape = (CMyShape *)pObj;
  }
}

Back to Top

Q:如何才能够获得当前选中对象的列表?

A:您可以调用下面的代码获得列表:

CFODrawShapeList *GetSelectShapes();

Back to Top

Q:我发现贵公司Basic Shapes.trs中的组件能旋转,矢量性很好,但是有些图形是不能满足我的需要,我能不能修改Basic Shapes.trs中的图形或者增加新的图形,如果能我该怎么做?更好的办法是我也能够做一个像它中的组件盒,其中放置我自己的组件.我能够用两种方法完成这个功能吗?

A:作为一套高扩展并包含了完整Source Code的组件库,您提高的要求只是Form++可以非常容易扩展的功能的一部分。事实上,目前我们提供的Basic Shapes.trs以及其他的所有在ToolBox中的组件,均只是Form++组件的一些范例。通过Form++您可以:
1、自由定义新的ToolBox页,您可以根据自己的需要增加新的ToolBox页面,也可以删除不需要的页面。同时您还可以定制ToolBox的外观(如:字体、图标、颜色边框等),我们在ToolBox对应的类(class)中封装了大量的函数,来帮助您完成各种修改。
2、增加新的组件,从大的方面讲,Form++的组件包含两个方面的类型:矢量组件和非矢量组件,非矢量组件目前有图像组件,而其他均为矢量组件。每个矢量组件都拥有旋转、放缩、移动、组合等属性。具体的某个组件需要这其中的哪些属性,均需要调用组件定义class的函数来控制。
3、Form++提供了一套非常完备而且容易的编程工具来帮助您快速的构建属于自己的新的组件,同时也提供了对系统提供的缺省组件的外观以及属性的修改。
4、Form++也提供了对组件具体的属性或者动作的修改功能。例如:您需要增加新的属性,您只需要使用Form++提供的自动代码产生程序,产生一个新的属性class,然后调用增加新属性给组件的函数,就可以在任何需要的时候定制组件的属性。
5、使用Form++增加的每个类型的组件均有一个属于自己的ID,ToolBox能够根据组件的ID来自动识别新的组件,也就是说,一旦您增加了新的组件后,您不需要做额外的工作,在ToolBox就自动具有了拖放的功能。
6、Form++对新增的组件除了能够放置在ToolBox中拖拉进入外,还能够支持通过鼠标直接绘制而成。例如:示例程序中的Rectangle组件。
总之,Form++能够100%的根据您的需要去定制各种功能。

Back to Top

Q:贵公司的组件盒中的组件是需要编程才能够增加,我能否将增加组件的功能增加到我的程序中,实现动态增加组件.我该怎么做?

A:没问题,对于最终用户来讲,他可以根据自己的需要增加属于自己的组件。下面是不需要编程而增加新组件的办法:
1、运行示例程序中的任何一个,比如:CustomMSample.
2、根据自己的需要在画布上,使用Form++提供的各种基本绘制工具,绘制一个复合组件。
3、按下Ctrl+A或者鼠标右键菜单的全部选择菜单。
4、按下Ctrl+C或者工具条上的复制按钮。
5、在ToolBox中按下鼠标右键,选择?#31896;贴?#33756;单。
6、您可以编辑新的组件的图标的外观。
这样您制作的复合组件就增加到了ToolBox中,以后您就可以像ToolBox的其他组件一样通过拖拉的方式拖入画布了。
您也可以参考示例程序FormBuilder的ToolBox的复合组件示例。

Back to Top 

Q:Form++支持什么操作系统?

A:Form++支持所有windows操作系统包括Windows95,Windows98,WindowsNT,Windows 2000,Windows XP

Back to Top

Q:Form++支持什么Visual C++版本?

A:Form++ can be compiled on VC++ versions starting from version 4 all the way to the upcoming VS.Net (with MFC 7) without any problems

Back to Top

Q: Is the Form++ UNICODE?
A:
Yes, Form++5.0 and all of its standard classes fully support UNICODE.

Back to Top

Q: What is one developer license?
A:
Developer license means the software can be installed on one developer's computer.
What does Team 4 and Team 8 stand for?
Team 4 stands for 4 developer licenses e.g. the software can be installed on 4 developer machines. Team 8 stands for 8 developer licenses.

Back to Top

Q: Can I offer component based on a Form++ source code as a competitor product?
A:No. We offer source code at a very special price.You cann't make a competitor product using any party of our source code.

Back to Top

Q: Only ever print inside the CPrintInfo::m_rectDraw area

A:Your printing code should not make assumptions about where it should print on the page, and make proper use of the CPrintInfo::m_rectDraw variable. This ensures that you will not overwrite margins/headers/footers that may be printed outside of your main OnPrint procedure.

pDC->TextOut(pInfo->m_rectDraw.left, pInfo->m_rectDraw.top, 
             "Only draw inside the reported m_rectDraw area") ;

Back to Top

Q: Getting a PrinterDC in OnPreparePrinting()

A:When OnPreparePrinting() is called in your CView derived class, you are generally required to setup the number of pages of output your document will need when printing, unless you are using the CPrintInfo::m_bContinuePrinting method. But it can be difficult to do this if you have no information on the printer resolution or page size. So at this point you need to get hold of the printer DC object that will be used. As the MFC print architecture would not create this until the OnBeginPrinting() function would be called, you have to create one yourself and release it after calculating the number of pages you want to print. To create such a printer DC you can use this code:

CDC dc ;
AfxGetApp()->CreatePrinterDC(dc) ;
    
...

// when finished with the DC, you should delete it
dc.DeleteDC() ;

This will create a printer DC for the default printer selected for you application.

Back to Top

Q: Getting the size of the printable page area

A:The printable area of a page on a printer is normally contained in the CPrintInfo::m_rectDraw member variable. A CPrintInfo object gets passed through to your CView overridden virtual functions. But in some cases, like in OnPreparePrinting(), OnBeginPrinting(), this member variable will not yet have been intialised. So you have to do it yourself.

pInfo->m_rectDraw.SetRect(0, 0, 
                          pDC->GetDeviceCaps(HORZRES), 
                          pDC->GetDeviceCaps(VERTRES)) ;

This gets the printable area of a printers page.

Back to Top

Q: Margins

A:In many cases you may want to have a user programmable margin around a page so that you do not over-print company logo's etc on headed paper, so you can set a user programmable range for you margins in inches. You can then convert these to device units and reserve that space on the page by changing the dimensions of the CPrintInfo::m_rectDraw variable. For example:

double LeftOffset = 0.5 ;       // in imperial inches!
double TopOffset = 0.5 ;        // in imperial inches!
double RightOffset = 0.5 ;      // in imperial inches!
double BottomOffset = 0.5 ;     // in imperial inches!
pInfo->m_rectDraw.DeflateRect(
    (int)(pDC->GetDeviceCaps(LOGPIXELSX) * LeftOffset),
    (int)(pDC->GetDeviceCaps(LOGPIXELSY) * TopOffset),
    (int)(pDC->GetDeviceCaps(LOGPIXELSX) * RightOffset),
    (int)(pDC->GetDeviceCaps(LOGPIXELSY) * BottomOffset)) ;

You will need to apply these changes to the m_rectDraw variable for every page printed, as the rectangle gets reset for every page loop in the MFC stock library code.

Back to Top

Q:Choosing a suitable font size for printing

A:When printing, choosing a font size that is suitable for the resolution of the printer in the past has been a hit and miss affair. I have had code that worked correctly on my development PC/printer setup, only to die horribly on a users PC/printer in Japan (e.g. the text generated was 1 pixel in height). Getting consistent output across printers can be done by selecting the font size based on the resolution reported by the printer:

CFont    font ;
LOGFONT  lf ;

::ZeroMemory(&lf, sizeof(LOGFONT));

// This aims to get a 12-point size font regardless of the 
// printer resolution
lf.lfHeight = -MulDiv(12, pDC->GetDeviceCaps(LOGPIXELSY), 72);
strcpy(lf.lfFaceName, "Arial");    //    with face name "Arial".
// make use of the font....

We set the LOGFONT::lfHeight member to a -ve value as this will get windows to select a good width for us which will give a nice proportional font.

Back to Top

Q:If you do not know how many pages you are going to print use CPrintInfo::m_bContinuePrinting

A:If, when printing your document, you did not know how many pages you were going to print until you actually printed (as calculating the actual page usage can be difficult), you can set the MFC print architecture to continue to request pages to print until you have finished with all your output. To do this, you should not sent a maximum page in your CView::OnPreparePrinting() function.

There are 2 places where you can choose to end the printing:

1: In your CView::OnPrepareDC() override

2: At the end of your CView::OnPrint() function when you have printed the last of your output

pInfo->m_bContinuePrinting = FALSE ;

Back to Top

Q:Use DIB's instead of DDB's

A:When printing bitmaps or icons to a printer DC, you should use a DIB (Device Independant Bitmap) rather than a DDB (Device Dependant Bitmap). This is because printer device drivers tend not to support BitBlt. You can end up spending a lot of time wondering why the bitmap appears in Print Preview (because the screen DC supports BitBlt) and not on your printed output (becuase the printer driver does not). So when printing, convert your image to a DIB and use StretchDIBBits to print the image. I have yet to find a printer where this technique would not work.

Here are some helpful functions that I have acquired from the web. I am not the original author of these, but I forget just where I got them from. But they are free source!

// this procedure extracts a single image from an image list into a DIB
HANDLE ImageToDIB( CImageList* pImageList, int iImageNumber, CWnd* pWnd)
{
    // Local Variables
    CBitmap     bitmap;
    CWindowDC    dc( pWnd );

    CDC         memDC;
    CRect        rect;
    CPalette    pal;
    IMAGEINFO   imageInfo;

    if (!pImageList->GetImageInfo( iImageNumber, &imageInfo ))
        {
        // Getting of the Imageinfos failed
        return NULL;
        }

    // Create compatible stuff and select Bitmap
    if (!memDC.CreateCompatibleDC(&dc ))
        {
        // Create failed
        return NULL;
        }

    if (!bitmap.CreateCompatibleBitmap(&dc, 
                                        imageInfo.rcImage.bottom-imageInfo.rcImage.top, 
                                        imageInfo.rcImage.right-imageInfo.rcImage.left))
        {
        // Create failed
        memDC.DeleteDC() ;
        return NULL;
        }

    CBitmap* pOldBitmap = memDC.SelectObject( &bitmap );
    if( NULL == pOldBitmap )
        {
        // Select failed
        memDC.DeleteDC() ;
        return NULL;
        }

    // Local Variables for Draw
    CPoint point( 0, 0);
    UINT nStyle = ILD_NORMAL;

    // Draw Image to the compatible DC
    if(!pImageList->Draw( &memDC, iImageNumber, point, nStyle ))
        {
        // Drawing of the Image failed
        memDC.SelectObject(pOldBitmap) ;
        VERIFY(bitmap.DeleteObject()) ;
        memDC.DeleteDC() ;
        return NULL;
        }

    // Create logical palette if device support a palette
    if( dc.GetDeviceCaps( RASTERCAPS ) & RC_PALETTE )
        {
        UINT        nSize   = sizeof(LOGPALETTE) + ( sizeof(PALETTEENTRY) * 256 );
        LOGPALETTE* pLP     = (LOGPALETTE*)new BYTE[nSize];
        pLP->palVersion     = 0x300;
        pLP->palNumEntries = (unsigned short)GetSystemPaletteEntries( dc, 0, 255, 
        pLP->palPalEntry );

        // Create the palette
        pal.CreatePalette( pLP );

        // Free memory
        delete[] pLP;
        }

    memDC.SelectObject( pOldBitmap );
    memDC.DeleteDC() ;

    // Convert the bitmap to a DIB
    HANDLE h = DDBToDIB(bitmap, BI_RGB, &pal );
    VERIFY(bitmap.DeleteObject()) ;
    return h ;
}


// DDBToDIB        - Creates a DIB from a DDB
// bitmap        - Device dependent bitmap
// dwCompression    - Type of compression - see BITMAPINFOHEADER
// pPal            - Logical palette
HANDLE DDBToDIB( CBitmap& bitmap, DWORD dwCompression, CPalette* pPal ) 
{
    BITMAP            bm;
    BITMAPINFOHEADER    bi;
    LPBITMAPINFOHEADER     lpbi;
    DWORD            dwLen;
    HANDLE            hDIB;
    HANDLE            handle;
    HDC             hDC;
    HPALETTE        hPal;


    ASSERT( bitmap.GetSafeHandle() );

    // The function has no arg for bitfields
    if( dwCompression == BI_BITFIELDS )
        return NULL;

    // If a palette has not been supplied use defaul palette
    hPal = (HPALETTE) pPal->GetSafeHandle();
    if (hPal==NULL)
        hPal = (HPALETTE) GetStockObject(DEFAULT_PALETTE);

    // Get bitmap information
    bitmap.GetObject(sizeof(bm),(LPSTR)&bm);

    // Initialize the bitmapinfoheader
    bi.biSize        = sizeof(BITMAPINFOHEADER);
    bi.biWidth        = bm.bmWidth;
    bi.biHeight         = bm.bmHeight;
    bi.biPlanes         = 1;
    bi.biBitCount        = (unsigned short)(bm.bmPlanes * bm.bmBitsPixel) ;
    bi.biCompression    = dwCompression;
    bi.biSizeImage        = 0;
    bi.biXPelsPerMeter    = 0;
    bi.biYPelsPerMeter    = 0;
    bi.biClrUsed        = 0;
    bi.biClrImportant    = 0;

    // Compute the size of the  infoheader and the color table
    int nColors = 0;
    if(bi.biBitCount <= 8)
        {
        nColors = (1 << bi.biBitCount);
        }
    dwLen  = bi.biSize + nColors * sizeof(RGBQUAD);

    // We need a device context to get the DIB from
    hDC = ::GetDC(NULL);
    hPal = SelectPalette(hDC,hPal,FALSE);
    RealizePalette(hDC);

    // Allocate enough memory to hold bitmapinfoheader and color table
    hDIB = GlobalAlloc(GMEM_FIXED,dwLen);

    if (!hDIB){
        SelectPalette(hDC,hPal,FALSE);
        ::ReleaseDC(NULL,hDC);
        return NULL;
    }

    lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);

    *lpbi = bi;

    // Call GetDIBits with a NULL lpBits param, so the device driver 
    // will calculate the biSizeImage field 
    GetDIBits(hDC, (HBITMAP)bitmap.GetSafeHandle(), 0L, (DWORD)bi.biHeight,
            (LPBYTE)NULL, (LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS);

    bi = *lpbi;

    // If the driver did not fill in the biSizeImage field, then compute it
    // Each scan line of the image is aligned on a DWORD (32bit) boundary
    if (bi.biSizeImage == 0){
        bi.biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8) 
                        * bi.biHeight;

        // If a compression scheme is used the result may infact be larger
        // Increase the size to account for this.
        if (dwCompression != BI_RGB)
            bi.biSizeImage = (bi.biSizeImage * 3) / 2;
    }

    // Realloc the buffer so that it can hold all the bits
    dwLen += bi.biSizeImage;
    handle = GlobalReAlloc(hDIB, dwLen, GMEM_MOVEABLE) ;
    if (handle != NULL)
        hDIB = handle;
    else
        {
        GlobalFree(hDIB);

        // Reselect the original palette
        SelectPalette(hDC,hPal,FALSE);
        ::ReleaseDC(NULL,hDC);
        return NULL;
        }

    // Get the bitmap bits
    lpbi = (LPBITMAPINFOHEADER)hDIB;

    // FINALLY get the DIB
    BOOL bGotBits = GetDIBits( hDC, (HBITMAP)bitmap.GetSafeHandle(),
                0L,                      // Start scan line
                (DWORD)bi.biHeight,      // # of scan lines
                (LPBYTE)lpbi             // address for bitmap bits
                + (bi.biSize + nColors * sizeof(RGBQUAD)),
                (LPBITMAPINFO)lpbi,      // address of bitmapinfo
                (DWORD)DIB_RGB_COLORS);  // Use RGB for color table

    if( !bGotBits )
    {
        GlobalFree(hDIB);
        
        SelectPalette(hDC,hPal,FALSE);
        ::ReleaseDC(NULL,hDC);
        return NULL;
    }

    SelectPalette(hDC,hPal,FALSE);
    ::ReleaseDC(NULL,hDC);
    return hDIB;
}

To use the above function(s) as an example code may be:

if (iImage >= 0)
    {
    HANDLE hDib ;
    hDib = ImageToDIB(&#8465;_list, iImage, this) ; // this is a dialog window in this example
    BITMAPINFOHEADER    *pBMI ;
    pBMI = (BITMAPINFOHEADER*)GlobalLock(hDib) ;
    int nColors = 0;
    if (pBMI->biBitCount <= 8)
        {
        nColors = (1 << pBMI->biBitCount);
        }
    // print the correct image
    ::StretchDIBits(dc.m_hDC,
                        pInfo.m_rectDraw.left, 
                        pInfo.m_rectDraw.top + cs.cy * j, 
                        cs.cy, 
                        cs.cy,
                        0, 
                        0, 
                        pBMI->biWidth,
                        pBMI->biHeight,
                        (LPBYTE)pBMI + (pBMI->biSize + nColors * sizeof(RGBQUAD)),
                        (BITMAPINFO*)pBMI,
                        DIB_RGB_COLORS, 
                        SRCCOPY);
    // free resources
    GlobalUnlock(hDib) ;
    GlobalFree(hDib) ;
    }

Back to Top

Q:请问我在绘制多边形的时候,如何才能够结束绘制!

A:双击鼠标即可!

Back to Top

Q:将form++用在一个实时系统中,关于在此类系统中做动画你们有何建议

A:开发基于动画的应用程序实际上是Form++的主要应用领域之一,在Form++中的所有对象都是矢量对象,比如一个椭圆,Windows的标准椭圆采用2个点来描述,而Form++采用了几十个点来描述,Windows标准椭圆没办法旋转而Form++的椭圆可以选准。此外,Form++封装了专门处理对象移动、放缩、旋转、定点编辑等大量的功能。这些功能将您开发动画系统的时候,只需要考虑对象的基本数据即可,而不用关心如何显示出来。除此之外,Form++还提供了所见及所得的打印功能,您能够在任何时刻,将动画移动的效果直接输出到打印机。当然,Form++大量的Class决不是一下子可以全部描述出来的,但有一点可以肯定,Form++开发动画系统将为您节省大量的宝贵时间。

Back to Top

Q:如何根据某一变量不同的值在画布的同一位置切换不同的Shape 如为0时 三角形  1时 圆形   2时 正方形?

A:每个不同类型的Form++组件Shape,均有自己特定的ID值,如果您需要将一种Shape转换为另外一种Shape,您需要改变ID值,同时如果是复杂组件(比如Tab组件同矩形组件的转换)还需要做相应的数据变换。

Back to Top

Q:如果我使用vc++.net怎样将form++添加到 vc++.net环境中?

A:Form++直接支持.net,您不需要做任何修改。
在连接库文件的时候,您需要指定为连接到Lib70目录。
同时,在运行时也需要将Lib70目录下的dll文件同运行程序的可执行文件放置在一起。
如果要在.net下编译Form++,请直接打开FOLib.dsw文件即可。

Back to Top

Q:We have been delivering about your Form++ product and it suits to our needs, but we have one critical requirement for our project that we haven t seen in it. Our software has to be able to save its drawing, or export it, to a dxf file format, so we would like to know how can we get this functionality in your product or besides it.

A:For default serialization you need to override Serialize() in all of the objects, the view ob, the frame ob and the view/doc to work use this format. For export/import you could just add a SerializeDXF method to all of your objects. Either way is easy, but somewhat laborious since there are a fair number of properties to convert.

We are not working on the .dxf filters. It would be great to have them as a sample though if you wouldn't mind contributing them. That way we would probably maintain them if the Form++-object properties every change

Back to Top

Q:如何在指定位置动态创建一个静态文本组件(CStaticShape)?

A:可以调用下面的代码来完成:

CRect rcTest;
rcTest = CRect(100,100,200,125);
CFOStaticShape *pReturn = new CFOStaticShape;
pReturn->AddRef();
pReturn->Create(rcTest,"");
CString strCaption = GetCurrentModel()->GetUniqueCaption(pReturn->GetType());
CString strName = GetCurrentModel()->GetUniqueName(pReturn->GetType());
pReturn->SetObjectCaption(strCaption);
pReturn->SetObjectName(strName);
pReturn->RemoveAllPorts();
pReturn->CreateDefaultPort(1,0.5);
GetCurrentModel()->GetFormObjects()->AddTail(pReturn);
pReturn->Release();

InvalidateShape(pReturn);

Back to Top

Q:我能够使用已经绘制好的*.wmf和*.emf文件作为我的组件吗?如果能怎样使用?

A:可以调用下面的代码来完成:

CRect rcTest;
rcTest = CRect(100,100,200,125);
CFOWMFShape *pReturn = new CFOWMFShape;
pReturn->AddRef();
pReturn->Create(rcTest,"");
pReturn->LoadImage("c:\\temp\\Arrows1.wmf");
CString strCaption = GetCurrentModel()->GetUniqueCaption(pReturn->GetType());
CString strName = GetCurrentModel()->GetUniqueName(pReturn->GetType());
pReturn->SetObjectCaption(strCaption);
pReturn->SetObjectName(strName);
pReturn->RemoveAllPorts();
pReturn->CreateDefaultPort(1,0.5);
GetCurrentModel()->GetFormObjects()->AddTail(pReturn);
pReturn->Release();

InvalidateShape(pReturn);

Back to Top

Q:如何动态创建一个CFOEllipseShape对象?

A:可以调用下面的代码来完成:

CRect rcTest;
rcTest = CRect(100,100,200,125);
CFOEllipseShape *pReturn = new CFOEllipseShape;
pReturn->AddRef();
pReturn->Create(rcTest,"");
CString strCaption = GetCurrentModel()->GetUniqueCaption(pReturn->GetType());
CString strName = GetCurrentModel()->GetUniqueName(pReturn->GetType());
pReturn->SetObjectCaption(strCaption);
pReturn->SetObjectName(strName);
pReturn->RemoveAllPorts();
pReturn->CreateDefaultPort(0.5,0.5);
GetCurrentModel()->GetFormObjects()->AddTail(pReturn);
pReturn->Release();

InvalidateShape(pReturn);

Back to Top

Q:如何动态创建一个CFOEllipseShape对象?

A:可以调用下面的代码来完成:

CRect rcTest;
rcTest = CRect(100,100,200,125);
CFOEllipseShape *pReturn = new CFOEllipseShape;
pReturn->AddRef();
pReturn->Create(rcTest,"");
CString strCaption = GetCurrentModel()->GetUniqueCaption(pReturn->GetType());
CString strName = GetCurrentModel()->GetUniqueName(pReturn->GetType());
pReturn->SetObjectCaption(strCaption);
pReturn->SetObjectName(strName);
pReturn->RemoveAllPorts();
pReturn->CreateDefaultPort(0.5,0.5);
GetCurrentModel()->GetFormObjects()->AddTail(pReturn);
pReturn->Release();

InvalidateShape(pReturn);

Back to Top

Q:如何动态创建一个CFORectShape对象?

A:可以调用下面的代码来完成:

CRect rcTest;
rcTest = CRect(100,100,200,250);
CFORectShape *pReturn = new CFORectShape;
pReturn->AddRef();
pReturn->Create(rcTest,"");
CString strCaption = GetCurrentModel()->GetUniqueCaption(pReturn->GetType());
CString strName = GetCurrentModel()->GetUniqueName(pReturn->GetType());
pReturn->SetObjectCaption(strCaption);
pReturn->SetObjectName(strName);
pReturn->RemoveAllPorts();
pReturn->CreateDefaultPort(0.5,0.5);
GetCurrentModel()->GetFormObjects()->AddTail(pReturn);
pReturn->Release();

InvalidateShape(pReturn);

Back to Top

Q:如何动态创建一个CFOPolygonShape对象?

A:可以调用下面的代码来完成:

CArray<CPoint,CPoint> ptArray;
ptArray.Add(CPoint(20,20));
ptArray.Add(CPoint(120,90));
ptArray.Add(CPoint(200,40));

CFOPolygonShape *pReturn = new CFOPolygonShape;
pReturn->AddRef();
pReturn->Create(&ptArray);
CString strCaption = GetCurrentModel()->GetUniqueCaption(pReturn->GetType());
CString strName = GetCurrentModel()->GetUniqueName(pReturn->GetType());
pReturn->SetObjectCaption(strCaption);
pReturn->SetObjectName(strName);
GetCurrentModel()->GetFormObjects()->AddTail(pReturn);
pReturn->Release();

InvalidateShape(pReturn);

Back to Top

Q:如何动态创建一个CFOLineShape 对象?

A:可以调用下面的代码来完成:

CArray<CPoint,CPoint> ptArray;
ptArray.Add(CPoint(20,20));
ptArray.Add(CPoint(120,90));
ptArray.Add(CPoint(200,40));

CFOLineShape *pReturn = new CFOLineShape;
pReturn->AddRef();
pReturn->Create(&ptArray);
CString strCaption = GetCurrentModel()->GetUniqueCaption(pReturn->GetType());
CString strName = GetCurrentModel()->GetUniqueName(pReturn->GetType());
pReturn->SetObjectCaption(strCaption);
pReturn->SetObjectName(strName);
GetCurrentModel()->GetFormObjects()->AddTail(pReturn);
pReturn->Release();

InvalidateShape(pReturn);

Back to Top

Q:我想改变画布的大小,但是上次你的解答是改变大小使用的是以像素为单位,我怎样以毫米或者厘米为单位改变画布的大小(因为我使用的图像只知道毫米或厘米大小),我怎样使用厘米或毫米为单位改变画布的大小

A:可以调用下面的代码来完成:

您可以直接调用下面的DataModel的函数来实现:
void SetPageSize(const float &fHorzMMValue,const float &fVertMMValue);
fHorzMMValue为水平毫米数,fVertMMValue为垂直毫米数
GetCurrentModel()->SetPageSize(5.0,6.0);
UpdateScrollSize();

Back to Top

Q:请问Ucancode做报表软件有何优势?如何实现表格的生成?

A:可以调用下面的代码来完成:

作为一个高扩展的C++的Class Library,Form++更重要的是扮演一个Framework的角色,这一点就如同MFC一样(MFC扮演更基础的角色):
问题一、关于报表设计程序?
开发基于报表的应用程序实际上是Form++的主要应用领域之一,一般来讲,如果要开发一个报表打印系统,应该包含两个方面的内容,一是报表设计器,二是报表打印程序,报表设计器将数据库中的字段按照一定的格式在屏幕上完成布局,如果使用Form++来开发报表设计程序,您就有了现成的功能强大的组件布局设计器,在这个设计器的画布上,您可以完成数据库字段的拖拉、移动、按照格式对齐以及按照网格停靠等功能,这些功能不需要您自己去编写任何代码。同时,Form++还提供了完善的打印机页面管理以及所见及所得的打印功能,一旦您在画布上创建好了组件,就可以直接打印出来。虽然一个功能强大的报表设计程序包含很多复杂的内容,但有一点可以肯定,Form++开发报表系统将为您节省大量的宝贵时间。
问题二、表格的生成?
没问题,对于最终用户来讲,他可以根据自己的需要增加属于自己的组件。一般来讲,我们可以使用Form++创建一个新的表格组件,这个组件的每个子对象就是一个静态文本组件或者是其他的一些标准组件,在Form++中直接支持复合组件的创建,比如我们可以将同样大小的静态文本组件排成两行两列就可以构成一个简单的表格。

Back to Top

Q:如何创建一个复合组件?

A:可以调用下面的代码来完成:

void CCustShapeView::OnCreateComposite() 
{
// TODO: Add your command handler code here
CRect rc = CRect(50,50,250,300);
CFOCompositeShape *pReturn = new CFOCompositeShape;
pReturn->AddRef();
pReturn->Create(rc,"");

CFOStaticShape *pText = pReturn->AddText("My home","My Home",CRect(0,0,200,50));
pText->SetBrushType(1);
pText->SetBkColor(RGB(255,0,0));
pText->SetPenStyle(PS_SOLID);
pText->SetNullPen(FALSE);

CFOStaticShape *pText1 = pReturn->AddText("Father","Steven",CRect(0,50,200,100));
pText1->SetBrushType(1);
pText1->SetBkColor(RGB(255,255,255));
pText1->SetPenStyle(PS_SOLID);
pText1->SetNullPen(FALSE);

CFOStaticShape *pText2 = pReturn->AddText("Mather","Cindy",CRect(0,100,200,150));
pText2->SetBrushType(1);
pText2->SetBkColor(RGB(255,255,255));
pText2->SetPenStyle(PS_SOLID);
pText2->SetNullPen(FALSE);

CFOStaticShape *pText3 = pReturn->AddText("Brother0","John",CRect(0,150,200,200));
pText3->SetBrushType(1);
pText3->SetBkColor(RGB(255,255,255));
pText3->SetPenStyle(PS_SOLID);
pText3->SetNullPen(FALSE);

CFOStaticShape *pText4 = pReturn->AddText("Brother1","Jack",CRect(0,200,200,250));
pText4->SetBrushType(1);
pText4->SetBkColor(RGB(255,255,255));
pText4->SetPenStyle(PS_SOLID);
pText4->SetNullPen(FALSE);


pReturn->RemoveAllPorts();
pReturn->CreateDefaultPort(0.5,0.5);
CString strCaption = GetCurrentModel()->GetUniqueCaption(pReturn->GetType());
CString strName = GetCurrentModel()->GetUniqueName(pReturn->GetType());
pReturn->SetObjectCaption(strCaption);
pReturn->SetObjectName(strName);
GetCurrentModel()->InsertShape(pReturn);
pReturn->Release();
pReturn = NULL;
}

Back to Top

Q:如何将选中组件向下移动50个像素?

A:可以调用下面的代码来完成:

void CCustShapeView::OnObjectMoveY50() 
{
// TODO: Add your command handler code here
if(m_listSelectComp.GetCount() >0)
{
int nMove = 50;
DoMoveAction(&m_listSelectComp, 0, nMove);
}

Back to Top

Q:如何将选中组件移动点(100,200)?

A:可以调用下面的代码来完成:

void CCustShapeView::OnObjectMoveTo() 
{
// TODO: Add your command handler code here
if(m_listSelectComp.GetCount() > 0)
{
CRect rcPos = GetCompsMaxRect(&m_listSelectComp);
CPoint ptMove;
ptMove = CPoint(100 - rcPos.TopLeft().x,200 - rcPos.TopLeft().y);
DoMoveAction(&m_listSelectComp, ptMove.x, ptMove.y);
}

Back to Top

Q:如何为直线添加末尾箭头?

A:可以调用下面的代码来完成:

void CCustShapeView::OnObjectRightarrow() 
{
// TODO: Add your command handler code here
if(m_listSelectComp.GetCount() <= 0)
{
return;
}

CFODrawShapeList lstUpdate;

CFODrawShape *pShape = NULL;
POSITION pos = m_listSelectComp.GetHeadPosition();
while(pos != NULL)
{
pShape = m_listSelectComp.GetNext(pos);
if(pShape != NULL)
{
if(pShape->IsKindOf(RUNTIME_CLASS(CFOLineShape)))
{
CFOLineShape *pLine = (CFOLineShape *)pShape;
int nArrowType = 3;
pLine->SetEndArrowType(nArrowType);
lstUpdate.AddTail(pLine); 
}
}
}
UpdateShapes(&lstUpdate);
}

Back to Top

Q:如何为直线添加开始箭头?

A:可以调用下面的代码来完成:


void CCustShapeView::OnObjectLeftarrow() 
{
// TODO: Add your command handler code here
if(m_listSelectComp.GetCount() <= 0)
{
return;
}

CFODrawShapeList lstUpdate;

CFODrawShape *pShape = NULL;
POSITION pos = m_listSelectComp.GetHeadPosition();
while(pos != NULL)
{
pShape = m_listSelectComp.GetNext(pos);
if(pShape != NULL)
{
if(pShape->IsKindOf(RUNTIME_CLASS(CF