DHL

Problems comparing two (in memory) bitmaps using memcmp

8 posts in this topic

Hi, 

I'm trying to compare two bitmaps (screenshots of the desktop) that I create using BitBlt. The bitmaps can be successfully saved to disk, but when I run the two bitmaps through a CompareBitmaps()-function I found in this thread, which calls memcmp, the script crashes with "Exit code: -1073741819". 

This crash only happens when I try to compare bitmaps that I got by using BitBlt. If I use the CompareBitmaps()-function on bitmaps created by _GDIPlus_ImageLoadFromFile, everything works fine. (I'm using AutoIT 3.3.6.1)

I'll attach my script that crashes, and the  CompareBitmaps() example script that works (which I got from the thread previosly mentioned)

My script, that for some reason crashes : 

#include <ScreenCapture.au3>
#include <GDIPlus.au3>
#include <WinAPI.au3>

_GDIPlus_Startup()

Local $hDesktop = _WinAPI_GetDesktopWindow()
$clientS = WinGetClientSize($hDesktop)
Local $Width = $clientS[0]
Local $Height = $clientS[1]

Local $hDC = _WinAPI_GetDC($hDesktop)
Local $memDC = _WinAPI_CreateCompatibleDC($hDC)
Local $memBmp = _WinAPI_CreateCompatibleBitmap($hDC, $Width, $Height)
_WinAPI_SelectObject ($memDC, $memBmp)
_WinAPI_BitBlt($memDC, 0, 0, $Width, $Height, $hDC, 0,0, $__SCREENCAPTURECONSTANT_SRCCOPY)
_WinAPI_DeleteDC($memDC)
_WinAPI_ReleaseDC($hDesktop, $hDC)

Local $hImage1 = _GDIPlus_BitmapCreateFromHBITMAP($memBmp)
_WinAPI_DeleteObject($memBmp)

_GDIPlus_ImageSaveToFile($hImage1, @ScriptDir & "\GDIPlus_Image1.jpg")

MsgBox(0, "Debug", "Screenshot taken & saved to disk. Ready to take new screenshot" )

Local $hDC2 = _WinAPI_GetDC($hDesktop)
Local $memDC2 = _WinAPI_CreateCompatibleDC($hDC2)
Local $memBmp2 = _WinAPI_CreateCompatibleBitmap($hDC2, $Width, $Height)
_WinAPI_SelectObject ($memDC2, $memBmp2)
_WinAPI_BitBlt($memDC2, 0, 0, $Width, $Height, $hDC2, 0,0, $__SCREENCAPTURECONSTANT_SRCCOPY)
_WinAPI_DeleteDC($memDC2)
_WinAPI_ReleaseDC($hDesktop, $hDC2)

Local $hImage2 =_GDIPlus_BitmapCreateFromHBITMAP($memBmp2)
_WinAPI_DeleteObject($memBmp2)

_GDIPlus_ImageSaveToFile($hImage2, @ScriptDir & "\GDIPlus_Image2.jpg")

MsgBox(0, "Debug", "Screenshot2 taken & saved to disk. Ready to compare images (from memory)" )

MsgBox(0, "bm1==bm2", CompareBitmaps($hImage1, $hImage2) )

; Clean up resources
_GDIPlus_ImageDispose($hImage1)
_GDIPlus_ImageDispose($hImage2)

; Shut down GDI+ library
_GDIPlus_ShutDown ()

Func CompareBitmaps($bm1, $bm2)

    $Bm1W = _GDIPlus_ImageGetWidth($bm1)
    $Bm1H = _GDIPlus_ImageGetHeight($bm1)

    $BitmapData1 = _GDIPlus_BitmapLockBits($bm1, 0, 0, $Bm1W, $Bm1H, $GDIP_ILMREAD, $GDIP_PXF32RGB)
    $Stride = DllStructGetData($BitmapData1, "Stride")
    $Scan0 = DllStructGetData($BitmapData1, "Scan0")

    $ptr1 = $Scan0
    $size1 = ($Bm1H - 1) * $Stride + ($Bm1W - 1) * 4
    $Bm2W = _GDIPlus_ImageGetWidth($bm2)
    $Bm2H = _GDIPlus_ImageGetHeight($bm2)
    $BitmapData2 = _GDIPlus_BitmapLockBits($bm2, 0, 0, $Bm2W, $Bm2H, $GDIP_ILMREAD, $GDIP_PXF32RGB)
    $Stride = DllStructGetData($BitmapData2, "Stride")
    $Scan0 = DllStructGetData($BitmapData2, "Scan0")
    $ptr2 = $Scan0
    $size2 = ($Bm2H - 1) * $Stride + ($Bm2W - 1) * 4

    $smallest = $size1
    If $size2 < $smallest Then $smallest = $size2
    $call = DllCall("msvcrt.dll", "int:cdecl", "memcmp", "ptr", $ptr1, "ptr", $ptr2, "int", $smallest)

    _GDIPlus_BitmapUnlockBits($bm1, $BitmapData1)
    _GDIPlus_BitmapUnlockBits($bm2, $BitmapData2)
    Return ($call[0]=0)
EndFunc  ;==>CompareBitmaps

 

Example Script (that basically does the same thing, but works fine)

#include <GDIPlus.au3>

_GDIPlus_Startup()
$fname1=FileOpenDialog("First image","","All images(*.bmp;*.jpg;*.png;)")
If $fname1="" Then Exit
$fname2=FileOpenDialog("Second image image","","All images(*.bmp;*.jpg;*.png;)")
If $fname2="" Then Exit
$bm1 = _GDIPlus_ImageLoadFromFile($fname1)
$bm2 = _GDIPlus_ImageLoadFromFile($fname2)

MsgBox(0, "bm1==bm2", CompareBitmaps($bm1, $bm2))
_GDIPlus_ImageDispose($bm1)
_GDIPlus_ImageDispose($bm2)
_GDIPlus_Shutdown()

Func CompareBitmaps($bm1, $bm2)

    $Bm1W = _GDIPlus_ImageGetWidth($bm1)
    $Bm1H = _GDIPlus_ImageGetHeight($bm1)
    $BitmapData1 = _GDIPlus_BitmapLockBits($bm1, 0, 0, $Bm1W, $Bm1H, $GDIP_ILMREAD, $GDIP_PXF32RGB)
    $Stride = DllStructGetData($BitmapData1, "Stride")
    $Scan0 = DllStructGetData($BitmapData1, "Scan0")

    $ptr1 = $Scan0
    $size1 = ($Bm1H - 1) * $Stride + ($Bm1W - 1) * 4


    $Bm2W = _GDIPlus_ImageGetWidth($bm2)
    $Bm2H = _GDIPlus_ImageGetHeight($bm2)
    $BitmapData2 = _GDIPlus_BitmapLockBits($bm2, 0, 0, $Bm2W, $Bm2H, $GDIP_ILMREAD, $GDIP_PXF32RGB)
    $Stride = DllStructGetData($BitmapData2, "Stride")
    $Scan0 = DllStructGetData($BitmapData2, "Scan0")

    $ptr2 = $Scan0
    $size2 = ($Bm2H - 1) * $Stride + ($Bm2W - 1) * 4

    $smallest = $size1
    If $size2 < $smallest Then $smallest = $size2
    $call = DllCall("msvcrt.dll", "int:cdecl", "memcmp", "ptr", $ptr1, "ptr", $ptr2, "int", $smallest)



    _GDIPlus_BitmapUnlockBits($bm1, $BitmapData1)
    _GDIPlus_BitmapUnlockBits($bm2, $BitmapData2)

    Return ($call[0]=0)


EndFunc  ;==>CompareBitmaps

 

Any one got a clue why my script crashes? 

Share this post


Link to post
Share on other sites



Trying a little bump. 

I still haven't figured out why the second script works fine and the first doesn't.

They both call 

DllCall("msvcrt.dll", "int:cdecl", "memcmp", "ptr", $ptr1, "ptr", $ptr2, "int", $smallest)

The main difference is that the second script get the bitmap-handles from

$bm1 = _GDIPlus_ImageLoadFromFile($fname1)

while the first (which crashes) acquires the bitmap-handles using BitBlt and these lines:

Local $hDC = _WinAPI_GetDC($hDesktop)
Local $memDC = _WinAPI_CreateCompatibleDC($hDC)
Local $memBmp = _WinAPI_CreateCompatibleBitmap($hDC, $Width, $Height)
_WinAPI_SelectObject ($memDC, $memBmp)
_WinAPI_BitBlt($memDC, 0, 0, $Width, $Height, $hDC, 0,0, $__SCREENCAPTURECONSTANT_SRCCOPY)
_WinAPI_DeleteDC($memDC)
_WinAPI_ReleaseDC($hDesktop, $hDC)

Local $hImage1 = _GDIPlus_BitmapCreateFromHBITMAP($memBmp)

Anyone who can point me in the right direction on how to solve this problem? 

Share this post


Link to post
Share on other sites

Yeah, I agree it must be crashing because of some type mismatch.

However, shouldn't 

_GDIPlus_BitmapCreateFromHBITMAP($memBmp)

and 

_GDIPlus_ImageLoadFromFile($fname1)

both return a handle to a bitmap object ?

It seems so by the docs. What am I missing?

https://www.autoitscript.com/autoit3/docs/libfunctions/_GDIPlus_BitmapCreateFromHBITMAP.htm

https://www.autoitscript.com/autoit3/docs/libfunctions/_GDIPlus_ImageLoadFromFile.htm

Share this post


Link to post
Share on other sites

As doc states one returns a bitmap object and the other an image object. So not both returning bitmap object as you state.

Bitmap class inherits from image I think. Maybe this function can convert.

https://msdn.microsoft.com/en-us/library/dd183485(VS.85).aspx

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

Its a while ago but maybe this one helps

https://www.autoitscript.com/autoit3/docs/libfunctions/_GDIPlus_BitmapCreateFromMemory.htm

and long ago I made this one

 

in that reference you see

If $BMPFile="SCREEN" Then
        $hbScreen=_ScreenCapture_Capture("",0,0,-1,-1,False)
        $pBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hbScreen); returns memory bitmap
    Else
;try to get a handle
        $handle = WinGetHandle($BMPFile)
        If @error Then
;Assume its an unknown handle so correct filename should be given
            $pBitmap = _GDIPlus_BitmapCreateFromFile($BMPFile)
        Else
            $hbScreen=_ScreenCapture_CaptureWnd("",$handle,0,0,-1,-1,False)
            $pBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hbScreen); returns memory bitmap
        EndIf
    EndIf

 

Edited by junkew

Share this post


Link to post
Share on other sites

Try this function instead:

Func _GDIPlus_ImageCompare($hImage1, $hImage2, $bFastCmp = True)
    Local Const $iW = _GDIPlus_ImageGetWidth($hImage1), $iH = _GDIPlus_ImageGetHeight($hImage1)
    If ($iW <> _GDIPlus_ImageGetWidth($hImage2)) Then Return SetError(1, 0, 0)
    If ($iH <> _GDIPlus_ImageGetHeight($hImage2)) Then Return SetError(2, 0, 0)
    Local $t = TimerInit()
    Local $tBitmapData1 = _GDIPlus_BitmapLockBits($hImage1, 0, 0, $iW, $iH, $GDIP_ILMREAD, $GDIP_PXF32ARGB)
    Local $tBitmapData2 = _GDIPlus_BitmapLockBits($hImage2, 0, 0, $iW, $iH, $GDIP_ILMREAD, $GDIP_PXF32ARGB)

    Local $iScan1 = DllStructGetData($tBitmapData1, "Scan0")
    Local $tPixel1 = DllStructCreate("int[" & $iW * $iH & "];", $iScan1)
    Local $iStride = Abs(DllStructGetData($tBitmapData1, "Stride"))

    Local $iScan2 = DllStructGetData($tBitmapData2, "Scan0")
    Local $tPixel2 = DllStructCreate("int[" & $iW * $iH & "];", $iScan2)

    If $bFastCmp Then
        $iResult = DllCall("msvcrt.dll", "int:cdecl", "memcmp", "ptr", $iScan1, "ptr", $iScan2, "int", ($iH - 1) * $iStride + ($iW - 1) * 4)[0]
    Else
        Local $iX, $iY, $iRowOffset, $iPixel1, $iPixel2, $aDiff[$iW * $iH + 1][3], $c = 1
        For $iY = 0 To $iH - 1
            $iRowOffset = $iY * $iW + 1
            For $iX = 0 To $iW - 1
                $iPixel1 = DllStructGetData($tPixel1, 1, $iRowOffset + $iX) ;get pixel color
                $iPixel2 = DllStructGetData($tPixel2, 1, $iRowOffset + $iX) ;get pixel color
                If $iPixel1 <> $iPixel2 Then
                    $aDiff[$c][0] = $iX & ", " & $iY
                    $aDiff[$c][1] = "0x" & Hex($iPixel1, 8)
                    $aDiff[$c][2] = "0x" & Hex($iPixel2, 8)
                    $c += 1
                EndIf
            Next
        Next
        $aDiff[0][0] = TimerDiff($t)
        $aDiff[0][1] = $iW
        $aDiff[0][2] = $iH
    EndIf

    _GDIPlus_BitmapUnlockBits($hImage1, $tBitmapData1)
    _GDIPlus_BitmapUnlockBits($hImage2, $tBitmapData2)

    If $bFastCmp Then Return SetError(0, Int(TimerDiff($t)), $iResult = 0)

    ReDim $aDiff[$c][3]
    Return $aDiff
EndFunc

 

1 person likes this

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯

Share this post


Link to post
Share on other sites

Thanks for pointing out that one returns a bitmap object and the other an image object, @junkew. I'm not really sure what the difference between those two are, but I guess they are different GDI+ objects.

I tried replacing the compare function in my code with @UEZ's _GDIPlus_ImageCompare and it just worked. I didn't have to do any "bitmap-object to image-object"-juggling. Amazing stuff and lightning fast. Thank you so much.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now

  • Similar Content

    • astrionn
      By astrionn
      So I had this Idea of creating a tooltip which shows me my ping.
      That itself was made quickly and I thought too add a couple features.
      I want the tooltip background to be a different color depending on the ping. (good ping is green, medium ping is yellow,...)
      So how do I color in a tooltip? google brought me to this: 
       
      where in the comments I found this:
      $s = "LOW" ToolTip($s, 0, 0, "Battery Information");, $icon) $H_TOOLTIP1 = WinGetHandle($s) DllCall("UxTheme.dll", "int", "SetWindowTheme", "hwnd", $H_TOOLTIP1, "wstr", "", "wstr", "") DllCall("user32.dll", "int", "SendMessage", "hwnd", $H_TOOLTIP1, "int", 1043, "int", 2552550, "int", 0) Sleep(1000) Which I then used in my code with different color codes... Trial and Error brought me these that I wanted to use:
       
      The Problem is if I loop through my code it only sets the color for the 1st loop and then sticks to it.
      The real problem is tho that I don't exactly understand the dllcalls... And I guess that's why it isn't working
      So if someone would be so awesome to explain to me how they work, or at least can give me a list of these parameters then I would really appreciate that and learn something new
      Obviously a solution to my problem is awesome aswell ^^
      I run this under Windows 8.1
      There is my code in a paste.
      https://pastebin.com/q525f7mS
    • Leo1906
      By Leo1906
      Hello Guys,
      once aggain I need your help on a DLL Topic
      I need to pass arguments to my function via a structure, because I am limited to only one argument that can be passed.
      But I don't think that thats so important.
      So here's my approach:
      C++ Code (just the important part):
      extern "C" { struct ParamStruct { const char* test1; const char* test2; const char* test3; int size; }; int testFunc(struct ParamStruct * params) { return params->size; } } And thats how I try to call the function using Autoit:
      Local $struct = "struct;char shapefile[128];char output[128];char filename[128];int size;endstruct" Local $tTest = DllStructCreate($struct) DllStructSetData($tTest, "test1", "Bla") DllStructSetData($tTest, "test2", "BlaBla") DllStructSetData($tTest, "test3", "BlaBlaBla") DllStructSetData($tTest, "size", 40) $dll = DLLOpen("myDLL.dll") $ret = DllCall($dll, "int:cdecl", "testFunc", "STRUCT*", DllStructGetPtr($tTest)) MsgBox(0, 0, $ret[0]) DllClose($dll) Just for testing I want the function to just return the integer value in the struct.
      But this aint working. I tested many things, but still I'm not able to get it running. I even don't know if the mistakes are in the C++ code or the Autoit code or both .. I'm not that skilled at C++ and also not that skilled at Autoit DLLCalls :-/
      I would really appreciate some help!
      Kind regards,
      leo
    • corgano
      By corgano
      What I am trying to accomplish is to simplify a .PNG image and convert it to use only a specified pallet of colors. Eg if I have a pallet of 0xFF0000, 0x00FF00, 0x0000FF, it would change every pixel in the image to one of those three colors by whichever color is closest.
       
      The simplest method I have tried is simply converting the image to a 16 bit bitmap, and that does simplify the pallet of the image, but I want to be able to specify what colors it specifies to. The other problem is the resulting saved .BMP file is much larger (file size) than the original, and I don't know if it's possible to make a 16 bit jpg.
       
      It looks like _GDIPlus_BitmapConvertFormat is the solution but the help file doesn't go into how to use the pallet and I couldn't find an example that did what I needed. Can anyone help me?
    • MagicSpark
      By MagicSpark
      Hello,
      can someone help me out with some DllCall in AU3.
      The relevant source of function and struct definition are as follows (in slightly modified form):
      typedef struct {     char    *host;     char    *key;     char    *value; } test_sender_value_t; /******************************************************************************  * Parameters: address   - [IN] server address                                *  *             port      - [IN] server port                                   *  *             source    - [IN] source IP, optional - can be NULL             *  *             values    - [IN] array of values to send                       *  *             count     - [IN] number of items in values array               *  *             result    - [OUT] the server response/error message, optional  *  *                                                                            *  * Return value: 0 - the values were sent successfully, result contains       *  *                         server response                                    *  *               -1 - an error occurred, result contains error message        *  *                                                                            *  ******************************************************************************/ TEST_API int test_sender_send_values(const char *address, unsigned short port, const char *source, const test_sender_value_t *values, int count, char **result);
      In AutoIt I use the following code to build the struct and call the dll:
      Global $struct = DllStructCreate("ptr ptrtostring1;ptr ptrtostring2;ptr ptrtostring3;") Global $string1 = DllStructCreate("char host[255];") DllStructSetData($string1, "host", "Test_Client") DllStructSetData($struct, "ptrtostring1", DllStructGetPtr($string1)) Global $string2 = DllStructCreate("char key[255];") DllStructSetData($string2, "key", "clientver") DllStructSetData($struct, "ptrtostring2", DllStructGetPtr($string2)) Global $string3 = DllStructCreate("char value[255];") DllStructSetData($string3, "value", "123456") DllStructSetData($struct, "ptrtostring3", DllStructGetPtr($string3)) Global $aCall = DllCall("C:\temp\test.dll", "int", "test_sender_send_values", _     "str", "192.168.1.2", _     "int", 80, _     "str", "192.168.1.3", _     "ptr", DllStructGetPtr($struct), _     "int", 1) If @error Then     ConsoleWrite("Error: " & @error & @CRLF)     exit 1 Else     ConsoleWrite("Success: " & $aCall[0] & @CRLF) EndIf
      If I ran the AU3-Script with SciTE I get the following output:
      !>12:00:00 AutoIt3.exe ended.rc:-1073741783 Can someone point me into the right direction. I must admit, that I'm very new to handling DLL-Calls and structs.
      But I've read down the forum threads and the AutoIt help.
      Thanks in advance.
       
    • likehu
      By likehu
      Hello,
      I have compiled a reference DLL in VS 2015 Community and this  DLL works fine with project for which it is used. There is an interface from which u can access functions in DLL.
      Developers stated that this DLL is almost universal and can be used with any language with minor changes.
      I am trying to access its function from Autoit script and got an error 3, after calling DLLCall - "function" not found in the DLL file.
      Please have a quick look, I feel I miss something in C++ library with exporting functions and I do not know what to add as I am new to C++.
      Thank you.
      Source files and script also attached.
       
      Here is my script.
      Local $dll = DllOpen("C:\Users\Home\Desktop\dll\user.dll") ConsoleWrite("$dll handle = " & $dll & @CRLF) ;$dll handle = 1 Local $result = DllCall($dll, "double:cdecl", "ProcessQuery", "str", "dll$mynumber") If @error > 0 Then ConsoleWrite("Error: " & @error & @CRLF) ;Error = 3 If IsArray($result) Then ConsoleWrite("Array returned!" & @CRLF & "dll$mynumber: " & result[1]) Else ConsoleWrite("$result is not array. : " & $result & @CRLF) ;$result = 0 EndIf DllClose($dll) And here is dll source. As I understand, function "ProcessQuery" exported with help of DLL_IMPLEMENTS
      user.h
      //****************************************************************************** // // This file is part of the OpenHoldem project // Download page: http://code.google.com/p/openholdembot/ // Forums: http://www.maxinmontreal.com/forums/index.php // Licensed under GPL v3: http://www.gnu.org/licenses/gpl.html // //****************************************************************************** // // Purpose: Very simple user-DLL as a starting-point // // DO NOT CHANGE ANYTHING IN THIS FILE! // // This Header defines an interface // Functions and data-types must exactly match. // //****************************************************************************** #ifndef _INC_USER_H #define _INC_USER_H // Import and export directives // for use by this DLL and by OpenHoldem #ifdef USER_DLL #define DLL_IMPLEMENTS extern "C" __declspec(dllexport) #define EXE_IMPLEMENTS extern "C" __declspec(dllimport) #else #define DLL_IMPLEMENTS extern "C" __declspec(dllimport) #define EXE_IMPLEMENTS extern "C" __declspec(dllexport) #endif // Number of saved table-states // This number must not be changed, as we do a "& 0xFF" // at various places to normalize the index. const int kNumberOfHoldemStatesForDLL = 256; // SHoldemePlayer // used for sequence of 256 consequive table-states // !!!! Needs 2 more cards for Omaha, if not entirely removed struct holdem_player { char m_name[16] ; //player name if known double m_balance ; //player balance double m_currentbet ; //player current bet unsigned char m_cards[2] ; //player cards unsigned char m_name_known : 1 ; //0=no 1=yes unsigned char m_balance_known : 1 ; //0=no 1=yes unsigned char m_fillerbits : 6 ; //filler bits unsigned char m_fillerbyte ; //filler bytes }; struct holdem_state { char m_title[64] ; //table title double m_pot[10] ; //total in each pot unsigned char m_cards[5] ; //common cards unsigned char m_is_playing : 1 ; //0=sitting-out, 1=sitting-in unsigned char m_is_posting : 1 ; //0=autopost-off, 1=autopost-on unsigned char m_fillerbits : 6 ; //filler bits unsigned char m_fillerbyte ; //filler byte unsigned char m_dealer_chair ; //0-9 holdem_player m_player[10] ; //player records }; // Functions implemented and exported by the DLL, // imported by OpenHoldem DLL_IMPLEMENTS double __stdcall ProcessQuery(const char* pquery); DLL_IMPLEMENTS void __stdcall DLLOnLoad(); DLL_IMPLEMENTS void __stdcall DLLOnUnLoad(); // Functions implemented and exported by OpenHoldem, // imported by the DLL EXE_IMPLEMENTS double __stdcall GetSymbol(const char* name_of_single_symbol__not_expression); EXE_IMPLEMENTS void* __stdcall GetPrw1326(); EXE_IMPLEMENTS char* __stdcall GetHandnumber(); EXE_IMPLEMENTS void __stdcall ParseHandList(const char* name_of_list, const char* list_body); EXE_IMPLEMENTS char* __stdcall ScrapeTableMapRegion(char* p_region, int& p_returned_lengh); EXE_IMPLEMENTS void __stdcall SendChatMessage(const char *message); EXE_IMPLEMENTS void __stdcall WriteLog(char* format, ...); // Variables exported by OpenHoldem // avoiding the message-mess of WinHoldem, // no longer sending any state-messages // http://www.maxinmontreal.com/forums/viewtopic.php?f=174&t=18642 EXE_IMPLEMENTS extern holdem_state state[kNumberOfHoldemStatesForDLL]; EXE_IMPLEMENTS extern int state_index; #endif // _INC_USER_H  
      user.cpp    Here is dll$mynumber parameter.
      //****************************************************************************** // // This file is part of the OpenHoldem project // Download page: http://code.google.com/p/openholdembot/ // Forums: http://www.maxinmontreal.com/forums/index.php // Licensed under GPL v3: http://www.gnu.org/licenses/gpl.html // //****************************************************************************** // // Purpose: Very simple user-DLL as a starting-point // // Required OpenHoldem version: 7.7.6 // //****************************************************************************** // Needs to be defined here, before #include "user.h" // to generate proper export- and inport-definitions #define USER_DLL // #define OPT_DEMO_OUTPUT if you are a beginner // who wants to see some message-boxes with output of game-states, etc. // It is disabled upon request, // * as it is not really needed // * as some DLL-users don't have MFC (atlstr.h) installed // http://www.maxinmontreal.com/forums/viewtopic.php?f=156&t=16232 #undef OPT_DEMO_OUTPUT #include "user.h" #include <conio.h> #include <windows.h> #ifdef OPT_DEMO_OUTPUT #include <atlstr.h> #endif OPT_DEMO_OUTPUT // Supporting macros #define HIGH_NIBBLE(c) (((c)>>4)&0x0F) #define LOW_NIBBLE(c) ((c)&0x0F) // Card macro #define RANK(c) ( ISKNOWN(c) ? HIGH_NIBBLE(c) : 0 ) #define SUIT(c) ( ISKNOWN(c) ? LOW_NIBBLE(c) : 0 ) #define ISCARDBACK(c) ((c) == CARD_BACK) #define ISUNKNOWN(c) ((c) == CARD_UNDEFINED) #define ISNOCARD(c) ((c) == CARD_NOCARD) #define ISKNOWN(c) (!ISCARDBACK(c) && !ISUNKNOWN(c) && !ISNOCARD(c)) // ProcessQuery() // Handling the lookup of dll$symbols DLL_IMPLEMENTS double __stdcall ProcessQuery(const char* pquery) { if (pquery==NULL) return 0; if (strncmp(pquery,"dll$mynumber",13)==0) { return 12345.67; } return 0; } // OnLoad and OnUnload() // called once and at the beginning of a session // when the DLL gets loaded / unloaded // Do initilization / finalization here. DLL_IMPLEMENTS void __stdcall DLLOnLoad() { #ifdef OPT_DEMO_OUTPUT MessageBox(NULL, "event-load", "MESSAGE", MB_OK); #endif OPT_DEMO_OUTPUT } DLL_IMPLEMENTS void __stdcall DLLOnUnLoad() { #ifdef OPT_DEMO_OUTPUT MessageBox(NULL, "event-unload", "MESSAGE", MB_OK); #endif OPT_DEMO_OUTPUT } // DLL entry point // Technically required, but don't do anything here. // Initializations belong into the OnLoad() function, // where they get executed at run-time. // Doing things here at load-time is a bad idea, // as some functionalitz might not be properly initialized // (including error/handling). BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: #ifdef OPT_DEMO_OUTPUT AllocConsole(); #endif OPT_DEMO_OUTPUT break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: #ifdef OPT_DEMO_OUTPUT FreeConsole(); #endif OPT_DEMO_OUTPUT break; } return TRUE; }  
      Source.zip
      DllAccess.au3