会 员 登 录
|
General
| Visual
Basic | Visual
C++ |
Web
| Delphi
| C++Builder
|
● 那个版本的
Visual C++ 支持 ActiveX
控件?
● 我动态创建了一个控件,它在我的机器上运行正常,但在其它机器上不能正常运行?
● 如何用正式版本的控件替换掉试用版本,而不会破坏原来用试用版做的工程?
● 如何在运行当中装载图片?
● 如何使用TREND 控件的AddXYArray 方法?
● 为什么Trend控件在一些激光打印机上不能打印?
那个版本的
Visual C++ 支持 ActiveX
控件?
世纪飞扬控件已经完全通过了Visual
C++ 4x、5.0、6.0 的测试。
Back
to Top
我动态创建了一个控件,它在我的机器上运行正常,但在其它机器上不能正常运行?
通常,一个商业控件只可以在设计模式下创建,在Visual
C++ 里可以在对话框当中使用放置控件。如果您的程序一定要动态创建我们的控件,您需要联系世纪飞扬,以达成新的许可协议(现有的许可协议不适合这种开发使用),世纪飞扬将提供一个新的版本以供您使用。
Back to Top
如何用正式版本的控件替换掉试用版本,而不会破坏原来用试用版做的工程?
● Unregister
反注册掉旧的控件。
● Register
注册新的控件。
● 打开您原来的包括旧控件的工程,会弹出一个对话框,提醒有些控件不能正常显示。
● 选择您
project workspace 中的 FileView
page。
● 删除掉旧控件已经生成的
.cpp 和
.h ,例如 _trend.cpp、font.cpp、picture.cpp、
_trend.h、font.h、picture.h 。
● 删除您工程目录中的这些文件。
● 选择菜单
" Add to
project "-> Compoent
and Controls ,引用新的控件到您的工程。
● 在对话框上放一个新的控件。
● 关闭并保存您的工程。
● 用记事本打开
.rc 文件,找到
dialog 资源描述一项,你可以发现旧控件和新控件的
classid ,用新
的 classid 替换掉旧的 classid
,保存 .rc 文件。
● 使用记事本打开
.dsw 文件。
● 删除旧控件生成的
classid ,保存
.dsw 文件。
● 重新打开您的工程,一切正常。
Back to Top
如何在运行当中装载图片?
以下例程实现了在运行当中为TREND 控件的BackPicture 属性添加图片。例程使用了一个按钮调用了文件对话框,这个方法适用于所有的图片文件。当然您不需要使用这个对话框和这么多代码。在设计模式下图片可以被很方便地装载并被编译到应用程序内部。
HRESULT _AfxCreateStreamOnFile(LPCTSTR
pszPath, LPSTREAM* ppstm,LONG* plSize)
{
ASSERT(pszPath != NULL);
ASSERT(ppstm != NULL);
*ppstm = NULL;
if (plSize != NULL)
*plSize = 0;
CFileStatus fstatus;
CFile file;
HRESULT hr = E_FAIL;
? LONG cb;
if (file.Open(pszPath, CFile::modeRead) &&
file.GetStatus(pszPath, fstatus) &&
((cb = fstatus.m_size) != -1))
{
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, cb);
LPVOID pvData = NULL;
if (hGlobal != NULL)
{
if ((pvData = GlobalLock(hGlobal)) != NULL)
{
BOOL bRead = (file.ReadHuge(pvData, cb) == (ULONG)cb);
GlobalUnlock(hGlobal);
if (bRead && SUCCEEDED(hr = CreateStreamOnHGlobal(hGlobal,
TRUE, ppstm)))
{
ASSERT(*ppstm != NULL);
if (plSize != NULL)
*plSize = fstatus.m_size;
hr = S_OK;
}
}
if (FAILED(hr))
GlobalFree(hGlobal);
}
else
hr = E_OUTOFMEMORY;
}
else
hr = E_ACCESSDENIED;
return hr;
}
void CVCDemoDlg::OnBitmapBUTTON()
{
CString strFilter, strTitle;
strFilter.LoadString(AFX_IDS_PICTUREFILTER);
strTitle.LoadString(AFX_IDS_PICTUREBROWSETITLE);
CFileDialog fdlg(TRUE, NULL, NULL,
OFN_FILEMUSTEXIST |
OFN_HIDEREADONLY |
OFN_PATHMUSTEXIST,
strFilter);
fdlg.m_ofn.lpstrTitle = strTitle;
int nResult = fdlg.DoModal();
SetFocus();
if (nResult != IDOK)
return;
CString strPath = fdlg.GetPathName();
LPSTREAM pstm = NULL;
LONG lSize;
HRESULT hr;
if (FAILED(hr = _AfxCreateStreamOnFile(strPath, &pstm,
&lSize)))
{
UINT idsText;
CString strText;
CString strCaption;
switch (GetScode(hr))
{
case E_OUTOFMEMORY:
idsText = AFX_IDP_PICTURETOOLARGE;
break;
case E_ACCESSDENIED:
idsText = AFX_IDP_PICTURECANTOPEN;
break;
default:
idsText = AFX_IDP_PICTUREREADFAILED;
break;
}
AfxFormatString1(strText, idsText, strPath);
strCaption.LoadString(AFX_IDS_PICTURE_PPG_CAPTION);
MessageBox(strText, strCaption, MB_OK | MB_ICONEXCLAMATION);
SetFocus();
return;
}
ASSERT(pstm != NULL);
LPPICTURE pPict;
if (SUCCEEDED(OleLoadPicture(pstm, lSize, FALSE, IID_IPicture,
(LPVOID *)&pPict)))
{
ASSERT(pPict != NULL);
LPPICTUREDISP pPictDisp = NULL;
if(SUCCEEDED(pPict->QueryInterface(IID_IPictureDisp,(LPVOID*)&pPictDisp)))
{
ASSERT(pPictDisp != NULL);
m_Trend1.SetBackPicture(pPictDisp);
pPictDisp->Release();
}
pPict->Release();
}
else
{
CString strText;
CString strCaption;
AfxFormatString1(strText, AFX_IDP_PICTURECANTLOAD, strPath);
strCaption.LoadString(AFX_IDS_PICTURE_PPG_CAPTION);
MessageBox(strText, strCaption, MB_OK | MB_ICONEXCLAMATION);
SetFocus();
}
pstm->Release();
}
Back to Top
如何使用 TREND 控件的 AddXYArray 方法?
以下例程实现了这个技巧。
void CTrendDemoDlg::OnTimer(UINT nIDEvent)
{
double x,y,v[10][2];
int i=0;
VARIANT varray;
SAFEARRAY *psafearray;
//Speed
switch (Speed)
{
case 0: //normal
x += 0.1;
y = 8 * sin(x) + 3 * cos(x * 0.5);
m_Trend1.AddY(0, y);
break;
case 1: //fast
for(i=0;i<15;i++)
{
x += 0.1;
y = 8 * sin(x) + 3 * cos(x * 0.5);
m_Trend1.AddY(0, y);
}
break;
case 2: //really
fast
psafearray = (SAFEARRAY *) new char[sizeof(SAFEARRAY)
+ sizeof(SAFEARRAYBOUND)];
psafearray->cDims = 2;
psafearray->cbElements = 8;
psafearray->rgsabound[0].cElements = 10;
psafearray->rgsabound[0].lLbound = 0;
psafearray->rgsabound[1].cElements = 2;
psafearray->rgsabound[1].lLbound = 0;
psafearray->pvData = (void *) v;
varray.vt = VT_ARRAY | VT_R8;
varray.parray = psafearray;
for(i=0;i<10;i++)
{
x += 0.1;
v[i][0] = x * 10.;
v[i][1] = 8 * sin(x) + 3 * cos(x * 0.5);
}
m_Trend1.AddXYArray(0, &varray);
break;
}
CDialog::OnTimer(nIDEvent);
}
Back to Top
为什么Trend控件在一些激光打印机上不能打印?
一些用户反映Trend 控件的PrintPic 方法在一些激光打印机上不能打印,现象为空走纸,没有输出内容,经我们跟踪调试,发现问题出在一个Windows 的标准API 函数上,这些激光打印机对这个API 支持有问题,具体原因不太清楚,可能是驱动程序的问题,我们已找到替代解决方案:
不要使用Trend 控件的PintPic 方法,直接输出控件的Image 属性到打印机,效果相同。
具体VB 例程为:
Private Sub cmdPrint_Click()
Printer.PaintPicture Trend1.Image, 0, 0
End Sub
如果您使用的开发工具是VC 的话,可以使用控件提供的hDC 属性,使用StretchBlt 直接输出到打印机:
void CTrendDlg::OnPrint()
{
//创建系统默认打印机的设备上下文
CPrintDialog pd(FALSE);
pd.GetDefaults();
HDC hdc = pd.CreatePrinterDC();
//打印机参数设置
DOCINFO DI;
DI.cbSize = sizeof(DOCINFO);
DI.fwType = 0;
DI.lpszDatatype = NULL;//"Trend Chart";
DI.lpszDocName = "Trend Chart";
DI.lpszOutput = NULL;
//以下得到控件的宽度和高度
RECT rctTrend;
::GetWindowRect((HWND)m_Trend1.GetHWnd(), &rctTrend);
long nWidth = rctTrend.right - rctTrend.left;
long nHeight = rctTrend.bottom - rctTrend.top;
//以下分别得到屏幕和打印机的DPI ,以及他们之间的比率,以校正打印图片的尺寸
int nScreenW = GetDeviceCaps((HDC)m_Trend1.GetHDC(),
LOGPIXELSX);
int nScreenH = GetDeviceCaps((HDC)m_Trend1.GetHDC(),
LOGPIXELSY);
int nPrintW = GetDeviceCaps(hdc, LOGPIXELSX);
int nPrintH = GetDeviceCaps(hdc, LOGPIXELSY);
float fRateX = float(nScreenW) / nPrintW;
float fRateY = float(nScreenH) / nPrintH;
//开始打印
StartDoc(hdc, (LPDOCINFO)&DI);
StartPage(hdc);
//::BitBlt(hdc, 0, 0, rctTrend.right - rctTrend.left,
rctTrend.bottom - rctTrend.top, (HDC)m_Trend1.GetHDC(),
0, 0, SRCCOPY);
::StretchBlt(hdc, 0, 0,int(nWidth / fRateX) , int(nHeight
/ fRateY), (HDC)m_Trend1.GetHDC(), 0, 0, nWidth, nHeight,
SRCCOPY);
EndPage(hdc);
EndDoc(hdc);
//打印结束
//删除创建的打印机设备上下文
DeleteDC(hdc);
}
Back to Top