GDI+のDLL実行について

ActiveBasicでのプログラミングでわからないこと、困ったことなどがあったら、ここで質問してみましょう(質問を行う場合は、過去ログやWeb上であらかじめ問題を整理するようにしましょう☆)。
メッセージ
作成者
jacoby
記事: 106
登録日時: 2006年6月02日(金) 18:20

GDI+のDLL実行について

#1 投稿記事 by jacoby »

AB4.24でアンチエイリアス(ドットのギザギザの目立たない)のラインを描画させたいと思っています。
GDI+での描画を考えてはいたのですが、これはGrahipcsクラスがABで使えないということであきらめていました。
そこでGraphicsクラスを使う所はC++で書いて、それをDLL関数にしてABから呼び出すようにしたら使えるかと思い以下のようなプログラムを書いてみました。

Paintイベント内の処理(デバイスコンテキスト・ハンドルからそのGraphicsオブジェクトを作成して、アンチエイリアス設定をして、線を描画する部分)をC++のDLL関数にして、それをABから呼び出すという形にしています。
GDI+の初期化と終了については呼び出し側のABで行っています。

しかし結果としては、これでは描画が行われないようです。
試しにDLLの中身をGDI+の描画では無く、単なるGDIの描画でラインを引くようにすると(MoveToEx & LineTo)、描画は行われます。(つまりDLL自体は実行されているものと思います。)

また、呼び出しをABでは無く、C++のプロジェクトから行うと、DLLは正しくアンチエイリアス・ラインを描画します。

このようなABからのGDI+のDLL実行について、お気づきのことがありましたら教えて下さい。


(以降プログラムです。長くなってしまってすみません。)

C++のDLL
「ヘッダー部」、「実装部」、「DEFファイル」の3つから成っています。
(VC++2010にて製作。プロジェクト名"AntiAlias")

ヘッダー部(AntiAlias.h)

コード: 全て選択


#pragma once

#include <comsvcs.h>
#include <windows.h>
#include <gdiplus.h>
#pragma comment(lib, "GdiPlus.lib")

using namespace Gdiplus;

//描画する線の情報を格納する構造体。(ライン描画DLL関数がABから受け取る構造体)。
struct DRAWLINE_ANTIALIAS_INFO{
 HDC hDC;             //デバイスコンテキスト・ハンドル。
 RECT rc;             //始点、終点座標。
 RGBQUAD col;         //ラインの色。
 BOOL antiAlias_flag; //アンチエイリアスをするかどうかのフラグ。
 DWORD width;         //線の太さ。
};

//ライン描画DLL関数のプロトタイプ宣言。
long __stdcall DrawLine_AntiAlias(DRAWLINE_ANTIALIAS_INFO* dai);


DLL関数実装部(AntiAlias.cpp)

コード: 全て選択


#include "AntiAlias.h"

//DLLメイン。
BOOL APIENTRY DllMain(HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
	return TRUE;
}

//アンチエイリアス・ライン描画DLL関数。
long __stdcall DrawLine_AntiAlias(DRAWLINE_ANTIALIAS_INFO* dai){
	
	//GDI+での描画
	Graphics MyGraphics(dai->hDC);

        //アンチエイリアスを施すかどうかをフラグを見て判断。
	if (dai->antiAlias_flag){
	  MyGraphics.SetSmoothingMode(SmoothingMode::SmoothingModeAntiAlias);
	}
	else{
	  MyGraphics.SetSmoothingMode(SmoothingMode::SmoothingModeDefault);
	}

        //描画処理。
	Pen Mypen1(Color(dai->col.rgbReserved, dai->col.rgbRed, dai->col.rgbGreen, dai->col.rgbBlue), dai->width);
	MyGraphics.DrawLine(&Mypen1, dai->rc.left, dai->rc.top, dai->rc.right, dai->rc.bottom);
 
 
 return 0;
}
DEFファイル

コード: 全て選択


LIBRARY	"AntiAlias"
EXPORTS
	DrawLine_AntiAlias
以上がC++のDLL部。


以下がABの呼び出し部プロジェクト。

コード: 全て選択


'-----------------------------------------------------------------------------
'  イベント プロシージャ
'-----------------------------------------------------------------------------
' このファイルには、ウィンドウ [MainWnd] に関するイベントをコーディングします。
' ウィンドウ ハンドル: hMainWnd

' TODO: この位置にグローバルな変数、構造体、定数、関数を定義します。
Type GdiplusStartupInput
    GdiplusVersion As Long
    DebugEventCallback As Long
    SuppressBackgroundThread As Long
    SuppressExternalCodecs As Long
End Type

'GDI+の初期化と終了処理の宣言。
Declare Function GdiplusStartup Lib "GDIPlus"  (ByRef token As Long, ByRef inputbuf As GdiplusStartupInput, ByRef outputbuf As Long) As Long
Declare Function GdiplusShutdown Lib "GDIPlus" (token As Long) As Long

Dim gdiPlus_si As GdiplusStartupInput
Dim gdiPlus_token As Long

'DLLに渡す「ラインの情報」構造体
Type DRAWLINE_ANTIALIAS_INFO
 hDC As HDC             'デバイスコンテキスト・ハンドル
 rc As RECT             '座標
 col As RGBQUAD         '色
 antiAlias_flag As BOOL 'アンチエイリアスフラグ(FALSE=アンチなし, TRUE=アンチ有り)
 width As DWORD         '線の太さ
End Type

Dim dai As DRAWLINE_ANTIALIAS_INFO

'DLL関数の宣言。
Declare Function DrawLine_AntiAlias Lib "AntiAlias.dll"(ByRef dai As DRAWLINE_ANTIALIAS_INFO) As Long


'-----------------------------------------------------------------------------
' ウィンドウメッセージを処理するためのコールバック関数

Function MainWndProc(hWnd As HWND, dwMsg As DWord, wParam As WPARAM, lParam As LPARAM) As DWord
	' TODO: この位置にウィンドウメッセージを処理するためのコードを記述します。

	' イベントプロシージャの呼び出しを行います。
	MainWndProc=EventCall_MainWnd(hWnd,dwMsg,wParam,lParam)
End Function


'-----------------------------------------------------------------------------
' ここから下は、イベントプロシージャを記述するための領域になります。
'デストロイ・イベント。
Sub MainWnd_Destroy()
      'GDI+の終了。
	GdiplusShutdown(gdiPlus_token)

	DrawLine_AntiAlias_GDIPlus_DestroyObjects()
	PostQuitMessage(0)
End Sub

'クリエイト・イベント。
Sub MainWnd_Create(ByRef CreateStruct As CREATESTRUCT)

 'クライアントエリアを白に変更。
 SetClassLong(hMainWnd, GCL_HBRBACKGROUND, GetStockObject(WHITE_BRUSH) As Long)

 'GDI+の初期化。
 GdiplusStartup(gdiPlus_token, gdiPlus_si, ByVal 0)

End Sub

'ペイント・イベント。
Sub MainWnd_Paint(hDC As HDC)

 '描画する線の情報をセット。
 dai.hDC=hDC
 dai.col.rgbRed=255
 dai.col.rgbGreen=0
 dai.col.rgbBlue=0
 dai.col.rgbReserved=255
 dai.rc.left=100
 dai.rc.top=100
 dai.rc.right=200
 dai.rc.bottom=120
 dai.width=1
 dai.antiAlias_flag=TRUE

 '描画用DLL関数の呼び出し。
 Dim ret As Long
 ret=DrawLine_AntiAlias(dai)

End Sub
HSABP

Re: GDI+のDLL実行について

#2 投稿記事 by HSABP »

GdiplusStartup()の戻り値は確認しましたか?
GdiplusStartup()がエラーになっています。

DLL関数実装部(AAA.cpp)

コード: 全て選択


#pragma once

#include <comsvcs.h>
#include <windows.h>
#include <gdiplus.h>
#pragma comment(lib, "GdiPlus.lib")

using namespace Gdiplus;

static ULONG_PTR gdiplusToken;

//描画する線の情報を格納する構造体。(ライン描画DLL関数がABから受け取る構造体)。
struct DRAWLINE_ANTIALIAS_INFO{
 HDC hDC;             //デバイスコンテキスト・ハンドル。
 RECT rc;             //始点、終点座標。
 RGBQUAD col;         //ラインの色。
 BOOL antiAlias_flag; //アンチエイリアスをするかどうかのフラグ。
 DWORD width;         //線の太さ。
};

//DLLメイン。
BOOL APIENTRY DllMain(HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
	return TRUE;
}

long GDIP_startup(void){
   GdiplusStartupInput gdiplusStartupInput;
   return GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
}

long GDIP_shutdown(void){
   GdiplusShutdown(gdiplusToken);
   return 0;
}


//アンチエイリアス・ライン描画DLL関数。
long __stdcall DrawLine_AntiAlias(DRAWLINE_ANTIALIAS_INFO* dai){
	
	//GDI+での描画
	Graphics MyGraphics(dai->hDC);

        //アンチエイリアスを施すかどうかをフラグを見て判断。
	if (dai->antiAlias_flag){
	  MyGraphics.SetSmoothingMode(SmoothingMode::SmoothingModeAntiAlias);
	}else{
	  MyGraphics.SetSmoothingMode(SmoothingMode::SmoothingModeDefault);
	}

    //描画処理。
	Pen Mypen1(Color(dai->col.rgbReserved, dai->col.rgbRed, dai->col.rgbGreen, dai->col.rgbBlue), dai->width);
	
	try {
		MyGraphics.DrawLine(&Mypen1, dai->rc.left, dai->rc.top, dai->rc.right, dai->rc.bottom);
	} catch(...) {
		return -1;
	}
 return 0;
}

DEFファイル(AAA.def)

コード: 全て選択


LIBRARY	"AAA"
EXPORTS
	GDIP_startup
	GDIP_shutdown
	DrawLine_AntiAlias
	
以上がC++のDLL部。


以下がABの呼び出し部プロジェクト。

コード: 全て選択


'-----------------------------------------------------------------------------
'  イベント プロシージャ
'-----------------------------------------------------------------------------
' このファイルには、ウィンドウ [MainWnd] に関するイベントをコーディングします。
' ウィンドウ ハンドル: hMainWnd

' TODO: この位置にグローバルな変数、構造体、定数、関数を定義します。

'DLLに渡す「ラインの情報」構造体
Type DRAWLINE_ANTIALIAS_INFO
 hDC As HDC             'デバイスコンテキスト・ハンドル
 rc As RECT             '座標
 col As RGBQUAD         '色
 antiAlias_flag As BOOL 'アンチエイリアスフラグ(FALSE=アンチなし, TRUE=アンチ有り)
 width As DWORD         '線の太さ
End Type

Dim dai As DRAWLINE_ANTIALIAS_INFO

'DLL関数の宣言。
Declare Function DrawLine_AntiAlias Lib "aaa.dll"(ByRef dai As DRAWLINE_ANTIALIAS_INFO) As Long
Declare Function GDIP_startup Lib "aaa.dll"() As Long

Declare Function GDIP_shutdown Lib "aaa.dll"() As Long

'-----------------------------------------------------------------------------
' ウィンドウメッセージを処理するためのコールバック関数

Function MainWndProc(hWnd As HWND, dwMsg As DWord, wParam As WPARAM, lParam As LPARAM) As DWord
	' TODO: この位置にウィンドウメッセージを処理するためのコードを記述します。

	' イベントプロシージャの呼び出しを行います。
	MainWndProc=EventCall_MainWnd(hWnd,dwMsg,wParam,lParam)
End Function


'-----------------------------------------------------------------------------
' ここから下は、イベントプロシージャを記述するための領域になります。
'デストロイ・イベント。
Sub MainWnd_Destroy()
      'GDI+の終了。
	GDIP_shutdown()

	'DrawLine_AntiAlias_GDIPlus_DestroyObjects()
	PostQuitMessage(0)
End Sub

'クリエイト・イベント。
Sub MainWnd_Create(ByRef CreateStruct As CREATESTRUCT)
Dim r As DWord

 'クライアントエリアを白に変更。
 SetClassLong(hMainWnd, GCL_HBRBACKGROUND, GetStockObject(WHITE_BRUSH) As Long)

 'GDI+の初期化。
  GDIP_startup()

End Sub

'ペイント・イベント。
Sub MainWnd_Paint(hDC As HDC)

 '描画する線の情報をセット。
 dai.hDC=hDC
 dai.col.rgbRed=255
 dai.col.rgbGreen=0
 dai.col.rgbBlue=0
 dai.col.rgbReserved=255
 dai.rc.left=100
 dai.rc.top=100
 dai.rc.right=200
 dai.rc.bottom=120
 dai.width=1
 dai.antiAlias_flag=TRUE

 '描画用DLL関数の呼び出し。
 Dim ret As Long
 ret=DrawLine_AntiAlias(dai)

End Sub