简体   繁体   中英

How to implement Interface to an abstract class which is constraint?

A few days ago I've tried to use (reference) a QRCode library .net with no interface in ms access vba unsuccesfully. So I did some research and people here guided me. So I decided to make the interface I followed this steps https://whoisburiedhere.wordpress.com/2011/07/12/creating-a-com-object-from-scratch-with-c/

I've been able to see the intellisense and create some of the objects and variables of other classess but I'm trouble with a class in which I see the Dispose() but I can't use the New in ms access:

[Dim QRCD as New QRCode]

I get an error the use of New is not valid but I can declare with the line:

Dim QRCD as QRCode

[I think that's not an object{ If I try to make it equals to QRData "That is no permited" error kicks in}] that class implements an abstract class which has constraints I've tried to put the interface in the abstract class and I get the error "Does not implement the method" if I put it in the Child class I can't create an object neither see any of the methods with the late binding. The QRCoder library can be found here. https://github.com/codebude/QRCoder This is the abstract class as it's provided.

{
using System;

public abstract class AbstractQRCode<T>
{
    protected QRCodeData qrCodeData;

    protected AbstractQRCode(QRCodeData data)
    {
        qrCodeData = data;
    }
    public abstract T GetGraphic(int pixelsPerModule);
}

}

This is the child class that implements it; it's already modified with the interface. Is not all the code but down are several methods all called GetGraphic(something as something) which are different from one another.

    [ComVisible(true)]
[Guid("It's filled in the program"), InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface neker
{

    Bitmap GetGraphic(int pixelsPerModule);
}
[ComVisible(true)]
[Guid(""), ClassInterface(ClassInterfaceType.AutoDual)]

public class QRCode :AbstractQRCode<Bitmap>, IDisposable, neker
{
    public QRCode(QRCodeData data) : base(data) {}

    public override Bitmap GetGraphic(int pixelsPerModule)
    {
        return GetGraphic(pixelsPerModule, Color.Black, Color.White, true);
    }

    public Bitmap GetGraphic(int pixelsPerModule, string darkColorHtmlHex, string lightColorHtmlHex, bool drawQuietZones = true)
    {
        return GetGraphic(pixelsPerModule, ColorTranslator.FromHtml(darkColorHtmlHex), ColorTranslator.FromHtml(lightColorHtmlHex), true);
    }

This is the sample code (also provided)

QRCodeGenerator qrGenerator = new QRCodeGenerator();
QRCodeData qrCodeData = qrGenerator.CreateQrCode("The text which should be encoded.", QRCodeGenerator.ECCLevel.Q);
QRCode qrCode = new QRCode(qrCodeData);
Bitmap qrCodeImage = qrCode.GetGraphic(20);

This is my code in VBA [This is in a Module]

Public Sub QRCreator(QRtext As String)
Dim QRCG As QRCoder.QRCodeGenerator
Set QRCG = New QRCoder.QRCodeGenerator
Dim QRCD As QRCodeData
Set QRCD = QRCG.CreateQRCode(QRtext, ECCLevel_Q, False)
Dim QRCO As QRCode
Set QRCO = Factory.CreateQRCode(QRCD)
Forms!Formulario1.[Oleobject].Picture = QRCO.GetGraphic(5)
End Sub

Public Sub InitiateProperties(Data As QRCodeData)
//I declared it as Variant since QRCode is not avaliable
Dim m_data As Variant
m_data = Data
End Sub

This is in another module[I use this modules to create the object with parameters] Pass arguments to Constructor in VBA

Public Function CreateQRCode(Data As QRCodeData) As QRCode
//you see the word new is missing If I run it it says "An object is required"

Set CreateQRCode = QRCode
CreateQRCode.InitiateProperties Data:=Data

End Function

How could I modify it to be usable from microsoft access 2013? Is another way to do it with no interfaces? Does access supports bitmaps in vba? I'm very new with all this stuff so thank you so much.

EDIT: THE REASON WHY I COULD'T MAKE IT WORK WAS COM VISIBLE DOESN´T SUPPORT CONSTRUCTORS WITH PARAMETERS, AND METHODS WITH OVERRIDES. THE ANSWER THEN IS HOW I WAS ABLE TO CREATE THE IMAGES ANYWAY.

Your COM object can't be created because the class doesn't have a default constructor. Rather than trying to expose the original API, you should create a single class with the methods matching your needs:

VBA usage:

Public Sub QRCreator(text As String)
  Dim qrc As New QRCoder.QRCodeGenerator
  Forms!Formulario1.[Oleobject].Picture = qrc.Create(text, CCLevel_Q, 5)
End Sub

.Net :

[Guid("C7CC4CA0-813A-431E-B92C-842A07735E72")]
[ComVisible(true), InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface _QRCodeGenerator {

    public IStdPicture Create(string text, int cclevel, int pixelsPerModule);

}


[ProgId("QRCoder.QRCodeGenerator")]
[Guid("4DC2C1F8-2727-4120-80E1-8475650D8547")]
[ComVisible(true), ClassInterface(ClassInterfaceType.None)]
[Description("...")]
public class QRCodeGenerator : _QRCodeGenerator, IDisposable {

    private QRCoder.QRCodeGenerator instance;

    public QRCodeGenerator() {
        instance = new QRCoder.QRCodeGenerator();
    }

    public IStdPicture Create(string text, int cclevel, int pixelsPerModule){
        var qrCodeData = instance.CreateQrCode(text, cclevel);
        var qrCode = new QRCoder.QRCode(qrCodeData);
        var bitmap = qrCode.GetGraphic(pixelsPerModule);
        return ImageToPicture(bitmap);
    }

    public void Dispose() {
        instance.Dispose();
    }

    private static IStdPicture ImageToPicture(Bitmap bitmap) {
        ...
    }
}

Well After checking, trying and failing I decided to change my perspective. So I did this

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using Interop;
using System.Runtime.InteropServices;
using stdole;
namespace QRCoder
{
[Guid("52724C82-F18C-460B-B48D-1F19E016F86E")]
[ComVisible (true) , InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IQRCodeGene
{
    string Create(string text, QRCodeGenerator.ECCLevel value, int pixelsPerModule);
}
[Guid("4F445AA5-D642-438B-A69A-429D621A3CB0")]
[ComVisible (true), ClassInterface(ClassInterfaceType.None)]
   public class QRCodeGene: IQRCodeGene, IDisposable
{
    private QRCodeGenerator Instance;
    public QRCodeGene()
    {
        Instance = new QRCodeGenerator();
    }
    public string Create(string text, QRCodeGenerator.ECCLevel value, int pixelsPerModule)
    {
        var qrCodeData = Instance.CreateQrCode(text, value);
        var qrCode = new QRCode(qrCodeData);
        var bitmap = qrCode.GetGraphic(pixelsPerModule);
// This line is the only modified by the provided in the code above.
        bitmap.Save("C:\\"+text+".bmp", System.Drawing.Imaging.ImageFormat.Bmp);
//I return this string for testing. I guess If removed the text wouldn't work.
        return ("Hello");
    }
    public void Dispose()
    {
        Instance.Dispose();
    }

}
}

The code above generates the QRCode of anything I would send trough this function in access VBA:

Public Sub QR(Text As String)
Dim QRC As New QRCodeGene
Dim x As String
x = QRC.Create(Text, ECCLevel_Q, 5)

End Sub

After that I just load the picture generated with and access.image control source. Thanks Florent B. for providing this code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM