Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Plugin System – an alternative to GetProcAddress and interfaces

, 25 May 2007
A powerful and extensible way of creating plugin-based applications
pluginsystem_src.zip
defmaker
defmaker.dsp
defmaker.dsw
DLL+EXE
Host.dsw
HostExe.dsp
BMPParser
BMPParser.dsp
Host
Host.dsp
Release
BMPParser.imp
Host.dll
HostExe.exe
TGAParser.imp
TGAParser
TGAParser.dsp
EXE
Host.dsp
Host.dsw
BMPParser
BMPParser.dsp
ImageParser
ImageParser.dsp
Release
BMPParser.imp
Host.exe
TGAParser.imp
TGAParser
TGAParser.dsp
Interface
Host.dsp
Host.dsw
BMPParser
BMPParser.dsp
Release
BMPParser.imp
Host.exe
TGAParser.imp
TGAParser
TGAParser.dsp
// Host.cpp - a plugin-based image viewer
// In this version the host is a single EXE that exports functionality to the plugins
//
// Part of the Plugin System tutorial
//
///////////////////////////////////////////////////////////////////////////////

#include <windows.h>
#include <Shlwapi.h>
#include <stdio.h>
#include "Host.h"
#include "ImageParser\ImageParser.h"

// the currently displayed bitmap
static HBITMAP g_Bitmap=NULL;

// a global list with all parsers
const int MAX_PARSERS=100;
CImageParser *g_Parsers[MAX_PARSERS];
int g_NumParsers=0;

// Adds the parser to the g_Parsers list
void AddParser( CImageParser *parser )
{
	g_Parsers[g_NumParsers++]=parser;
}

// Loads all plugins in the same folder as the EXE
void LoadPlugins( void )
{
	char path[_MAX_PATH];
	GetModuleFileName(NULL,path,_MAX_PATH);
	*PathFindFileName(path)=0;
	char spec[_MAX_PATH];
	sprintf(spec,"%s*.imp",path);
	WIN32_FIND_DATA data;
	// find all DLLs
	HANDLE h=FindFirstFile(spec,&data);
	if (h!=INVALID_HANDLE_VALUE) {
		do {
			char fname[_MAX_PATH];
			sprintf(fname,"%s%s",path,data.cFileName);
			LoadLibrary(fname);
		} while (FindNextFile(h,&data));
		FindClose(h);
	}
}

// Loads an image file
void LoadImage( const char *fname )
{
	// find the parser for that type and load the image
	char ext[_MAX_EXT];
	_splitpath(fname,NULL,NULL,NULL,ext);
	for (int i=0;i<g_NumParsers;i++)
		if (g_Parsers[i]->SupportsType(ext)) {
			g_Bitmap=g_Parsers[i]->ParseFile(fname);
			break;
		}
}

LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
	if (uMsg==WM_DESTROY)
		PostQuitMessage(0);

	if (uMsg==WM_PAINT) {
		// paints the window
		// if a bitmap is loaded - draw the bitmap
		// otherwise draw a text prompt
		PAINTSTRUCT ps;
		HDC hdc=BeginPaint(hwnd,&ps);
		if (g_Bitmap) {
			HDC hsrc=CreateCompatibleDC(hdc);
			SelectObject(hsrc,g_Bitmap);
			BITMAP bmp;
			GetObject(g_Bitmap,sizeof(bmp),&bmp);
			BitBlt(hdc,0,0,bmp.bmWidth,bmp.bmHeight,hsrc,0,0,SRCCOPY);
			DeleteDC(hsrc);
		}
		else {
			SelectObject(hdc,GetStockObject(DEFAULT_GUI_FONT));
			SetBkMode(hdc,TRANSPARENT);
			SetTextColor(hdc,0xFFFFFF);
			const char *s="Drop an image file here";
			TextOut(hdc,0,0,s,strlen(s));
		}
		EndPaint(hwnd,&ps);
		return 0;
	}

	if (uMsg==WM_DROPFILES) {
		// destroy the previous image
		if (g_Bitmap) DeleteObject(g_Bitmap);
		g_Bitmap=NULL;

		// get the file name
		HDROP hDrop=(HDROP)wParam;
		char fname[_MAX_PATH];
		DragQueryFile(hDrop,0,fname,_MAX_PATH);
		DragFinish(hDrop);

		// load the image file
		LoadImage(fname);
		InvalidateRect(hwnd,NULL,TRUE);
		return 0;
	}

	return DefWindowProc(hwnd,uMsg,wParam,lParam);
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
	// Create main window
	WNDCLASS wc;
	memset(&wc,0,sizeof(wc));
	wc.style=CS_VREDRAW|CS_HREDRAW;
	wc.lpfnWndProc=WindowProc;
	wc.hInstance=hInstance;
	wc.hCursor=LoadCursor(NULL,IDC_CROSS);
	wc.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
	wc.lpszClassName="ImageViewer";
	RegisterClass(&wc);
	HWND main=CreateWindowEx(WS_EX_APPWINDOW,"ImageViewer","ImageViewer",WS_OVERLAPPEDWINDOW|WS_VISIBLE|WS_CLIPCHILDREN,
		CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL);
	DragAcceptFiles(main,TRUE);
	LoadPlugins();

	// Process messages
	while (1) {
		MSG msg;
		if (!GetMessage(&msg,0,0,0)) break;
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return 0;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Ivo Beltchev
Software Developer (Senior)
United States United States
Ivo started programming in 1985 on an Apple ][ clone. He graduated from Sofia University, Bulgaria with a MSCS degree. Ivo has been working as a professional programmer for over 12 years, and as a professional game programmer for over 10. He is currently employed in Pandemic Studios, a video game company in Los Angeles, California.

| Advertise | Privacy | Mobile
Web04 | 2.8.140814.1 | Last Updated 25 May 2007
Article Copyright 2007 by Ivo Beltchev
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid