我的环境是win7+Qt5.1
之前在网上找了一些例子, 怎么调试都不出来. 原来是窗口属性的问题.
解决方法:
网上的例子: setAttribute(Qt::WA_PaintOnScreen, true);
Note: This flag is only supported on X11 and it disables double buffering.
看文档发现这个属性只能用于X11环境.
修改为:
setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground, true);
具体代码如下:
D3DWidget.h
#ifndef QD3DWIDGET_H
#define QD3DWIDGET_H
#include <QWidget>
#include <d3d9.h>
#include <d3dx9.h>
extern LPDIRECT3D9 g_pD3D;
extern LPDIRECT3DDEVICE9 g_pDevice;
extern LPDIRECT3DVERTEXBUFFER9 g_pVertexBuffer;
extern LPDIRECT3DINDEXBUFFER9 g_pIndexBuffer;
HRESULT Init3D(HWND hWnd);
struct CUSTOMVERTEX
{
float x,y,z;
DWORD color;
};
#define D3DFVF_CUSTOMVERTEXT (D3DFVF_XYZ|D3DFVF_DIFFUSE)
class QD3DWidget : public QWidget
{
Q_OBJECT
public:
QD3DWidget(QWidget *parent = NULL);
~QD3DWidget();
//reimplement paintEngine
QPaintEngine *paintEngine()const;
protected:
void paintEvent(QPaintEvent *ev);
virtual void initialize3D();
virtual void paintD3D();
virtual bool initGemetry();
virtual void d3dInit();
virtual void d3dDraw();
virtual void render();
public:
bool initialized()const{
return fInit;
}
public slots:
void rotateTriangle();
private:
void setupMatrices();
private:
bool fInit;
int fRotateY;
};
#endif // QD3DWIDGET_H
D3DWidget.cpp
#include "QD3DWidget.h"
#include "D3D9.h"
#include <QTimer>
#include <QMessageBox>
LPDIRECT3D9 g_pD3D = NULL;
LPDIRECT3DDEVICE9 g_pDevice = NULL;
LPDIRECT3DVERTEXBUFFER9 g_pVertexBuffer = NULL;
LPDIRECT3DINDEXBUFFER9 g_pIndexBuffeer = NULL;
HRESULT Init3D(HWND hWnd)
{
//create d3d object
if(NULL ==(g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)))
return E_FAIL;
//set up the structure used to create the D3DDevice
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp , sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;//
//create the d3ddevice
if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_REF,hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING,&d3dpp,&g_pDevice)))
return E_FAIL;
//turn off culling , so we can see the front and back of the triangle
g_pDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
//turn off d3d lighting , since we are prodving our own vertex colors
g_pDevice->SetRenderState(D3DRS_LIGHTING,FALSE);
g_pDevice->SetRenderState(D3DRS_ANTIALIASEDLINEENABLE,TRUE);
g_pDevice->SetRenderState(D3DRS_ZENABLE,D3DZB_TRUE);
return S_OK;
}
QD3DWidget::QD3DWidget(QWidget *parent)
: QWidget(parent)
, fInit(false)
, fRotateY(0)
{
setFixedSize(400,400);
setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground, true);
}
QD3DWidget::~QD3DWidget()
{
g_pIndexBuffeer->Release();
g_pVertexBuffer->Release();
g_pDevice->Release();
g_pD3D->Release();
}
QPaintEngine * QD3DWidget::paintEngine()const
{
return NULL;
}
void QD3DWidget::initialize3D()
{
Init3D((HWND)winId());
initGemetry();
fInit = true;
}
void QD3DWidget::paintD3D()
{
render();
}
void QD3DWidget::paintEvent(QPaintEvent *ev)
{
if(updatesEnabled()){
d3dDraw();
}
}
void QD3DWidget::d3dInit()
{
initialize3D();
}
void QD3DWidget::d3dDraw()
{
if(!initialized()){
d3dInit();
}
paintD3D();
}
void QD3DWidget::render()
{
g_pDevice->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(255,0,255),1.0f,0);
g_pDevice->BeginScene();
setupMatrices();
//set fvf
g_pDevice->SetFVF(D3DFVF_CUSTOMVERTEXT);
//bind vertex buffer data to device source data
g_pDevice->SetStreamSource(0,g_pVertexBuffer,0,sizeof(CUSTOMVERTEX));
//draw
//g_pDevice->DrawPrimitive(D3DPT_TRIANGLELIST,0,1);
g_pDevice->SetIndices(g_pIndexBuffeer);
g_pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,4,0,4);
g_pDevice->EndScene();
g_pDevice->Present(NULL,NULL,NULL,NULL);
}
bool QD3DWidget::initGemetry()
{
// 平面三角形原形
//CUSTOMVERTEX vertices[] = {
// {
// -1.0f,-1.0f,0.0f,D3DCOLOR_XRGB(255,0,0)//red
// },
// {
// 0.0f,1.0f,0.0f,D3DCOLOR_XRGB(0,255,0)//green
// },
// {
// 1.0f,-1.0f,0.0f,D3DCOLOR_XRGB(0,0,255)//blue
// }
//};
// 立体三角形原形
CUSTOMVERTEX vertices[] = {
{0.0f,1.0f,0.0f,D3DCOLOR_XRGB(0,255,0)},
{-1.0f,-1.0f,-0.577f,D3DCOLOR_XRGB(255,0,0)},
{1.0f,-1.0f,-0.577f,D3DCOLOR_XRGB(0,255,255)},
{0.0f,-1.0f,1.155f,D3DCOLOR_XRGB(0,0,255)}
};
WORD indices[] ={0,2,1,0,3,2,0,1,3,1,2,3};
//create vertex buffer
if(FAILED(g_pDevice->CreateVertexBuffer(sizeof(vertices),0,D3DFVF_CUSTOMVERTEXT,D3DPOOL_DEFAULT,&g_pVertexBuffer,NULL)))
return false;
//store the vertex data into buffer
void *pVertices;
g_pVertexBuffer->Lock(0,sizeof(vertices),(void**)&pVertices,0);
memcpy(pVertices,vertices,sizeof(vertices));
g_pVertexBuffer->Unlock();
//create index buffer
g_pDevice->CreateIndexBuffer(sizeof(indices),0,D3DFMT_INDEX16,D3DPOOL_DEFAULT,&g_pIndexBuffeer,NULL);
//store the index data
void *pIndices;
g_pIndexBuffeer->Lock(0,sizeof(indices),(void**)&pIndices,0);
memcpy(pIndices,indices,sizeof(indices));
g_pIndexBuffeer->Unlock();
return true;
}
void QD3DWidget::setupMatrices()
{
float angle = fRotateY *D3DX_PI/180;
D3DXMATRIX matWorld;
D3DXMatrixRotationY(&matWorld,angle);
//set the world matrix
g_pDevice->SetTransform(D3DTS_WORLD,&matWorld);
D3DXVECTOR3 eye(0.0f,3.0f,-5.0f);
D3DXVECTOR3 lookat(0.0f,0.0f,0.0f);
D3DXVECTOR3 up(0.0f,1.0f,0.0f);
D3DXMATRIX matView;
//calculate the view matrix
D3DXMatrixLookAtLH(&matView,&eye,&lookat,&up);
g_pDevice->SetTransform(D3DTS_VIEW,&matView);
//perspective matrix
D3DXMATRIXA16 matProj;
D3DXMatrixPerspectiveFovLH(&matProj,D3DX_PI/4,1.0f,1.0f,100.0f);
g_pDevice->SetTransform(D3DTS_PROJECTION,&matProj);
}
void QD3DWidget::rotateTriangle()
{
fRotateY+=2;
if(fRotateY>360)
fRotateY=0;
update();
}
QTestWidget.h
#ifndef QTESTWIDGET_H
#define QTESTWIDGET_H
#include <QWidget>
#include <QtCore>
#include "qd3dwidget.h"
class QTestWidget : public QWidget
{
Q_OBJECT
public:
QTestWidget(QWidget *parent=NULL);
~QTestWidget();
public slots:
void startRotate();
void endRotate();
private:
QD3DWidget * fD3DWidget;
QTimer fTimer;
};
#endif // QTESTWIDGET_H
QTestWidget.cpp
#include "QTestWidget.h"
#include <QPushButton>
#include <QGridLayout>
QTestWidget::QTestWidget(QWidget *parent)
: QWidget(parent)
,fTimer(this)
{
fD3DWidget = new QD3DWidget(this);
QGridLayout *layout = new QGridLayout(this);
layout->addWidget(fD3DWidget,0,0,1,2);
QPushButton *rotateBt = new QPushButton("start rotate");
QPushButton *endBt = new QPushButton("end rotate");
layout->addWidget(rotateBt,1,0);
layout->addWidget(endBt,1,1);
connect(rotateBt,SIGNAL(clicked()),this,SLOT(startRotate()));
connect(endBt,SIGNAL(clicked()),this,SLOT(endRotate()));
connect(&fTimer,SIGNAL(timeout()),fD3DWidget,SLOT(rotateTriangle()));
layout->setContentsMargins(0,0,0,0);
layout->setSpacing(0);
}
QTestWidget::~QTestWidget()
{
}
void QTestWidget::startRotate()
{
fTimer.start(10);
}
void QTestWidget::endRotate()
{
fTimer.stop();
}
main.cpp
#include "testqq.h"
#include <QtWidgets/QApplication>
#include "QTestWidget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTestWidget w;
w.show();
return a.exec();
}
Link的时候, 添加这几个库:
d3d9.lib
d3dx9.lib
winmm.lib