加载图片可滚动&鼠标点击时获取x,y [英] load picture scrollable & get x,y when mouseclick

查看:63
本文介绍了加载图片可滚动&鼠标点击时获取x,y的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要使用Visual C ++ 2008在C语言中使用window api 32位编程帮助。



在窗口中从命令行加载图片路径/文件名。

但是如果工作滚动条更大的话。

鼠标点击图片的xy不是来自窗口客户区。



有没有人提出建议或示例?

解决方案

今晚我在等待某人的时候有点闲暇,所以决定有一点一出戏我没有打扰错误检查,你应该自己添加。我还选择了一种类似于编程许多不同窗口类时使用的MS的样式,如(重新设计的)Wine项目的部分内容。 ( https://github.com/wine-mirror/wine/tree/master/dlls/comctl32 [ ^ ] )



我试图让它与之交互变得非常简单。



首先,您必须注册课程 - 您可以在程序启动期间,在屏幕上显示任何内容之前执行此操作。



接下来,我定义了两条消息。 IM_SETIMAGE和IM_GETCLICKPOS。您可以显式发送这些消息,也可以使用提供的宏。

如果您选择自己发送这些消息,您只需要知道:



IM_SETIMAGE期望lParam保留新图像的HBITMAP 。返回值是前一个图像(如果有的话,否则为NULL)



IM_GETCLICKPOS没有参数并返回最后一次点击图像中的位置(您会收到通知通过WM_COMMAND消息的点击次数)。 lo阶词包含X位置,hi阶词包含Y位置。图像左侧/上方的位置返回负值。



背景颜色不能从包含的应用程序中自定义,但您可以轻松添加代码来处理此问题情况,或者更简单地说,编辑onImgWindowEraseBackground上的函数。



代码远非完美,但应该有助于提供一个良好的起点。你还有一些工作要做。虽然你提到将文件的名称传递给程序以便选择图像,但我建议你稍微复杂一点,然后创建一个配置文件。在此文件中,您可以包括以下内容:(1)图像文件的名称(2)感兴趣区域的数量(3)包围这些区域的多边形点的坐标对。



也许是这样的:

------------ config.txt ----------- -

图片:image.bmp

保利数:3

Apple:10,10,20,10,20,20,10, 20

西瓜:100,100,200,100,200,200,100,200

三角形:50,50,75,75,25,75

- --------------------------------





对于一个基本的使用示例,我将以下对话框应用程序放在一起。 (用Code :: Blocks编写,用MinGW构建)



main.cpp

  #include   <   windows.h  >  
#include < commctrl.h >
#include < stdio.h >
#include resource.h
#include ../ scrollImage / imgWindow.h

HINSTANCE hInst ;

BOOL CALLBACK DlgMain(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
switch (uMsg )
{
case WM_INITDIALOG:
{
HBITMAP img;
img =(HBITMAP)LoadImage(hInst, image.bmp,IMAGE_BITMAP,< span class =code-digit> 0 , 0 ,LR_LOADFROMFILE);
ImageWindow_SetImage(GetDlgItem(hwndDlg,IDC_IMAGE_WINDOW),img);
}
return TRUE;

case WM_CLOSE:
{
EndDialog(hwndDlg, 0 < /跨度>);
}
return TRUE;

case WM_COMMAND:
{
switch ( LOWORD(wParam))
{
case IDC_IMAGE_WINDOW:
LPARAM clickPos = ImageWindow_GetClickPos((HWND)lParam);
short xPos = LOWORD(clickPos);
short yPos = HIWORD(clickPos);
char msg [ 32 ];
sprintf(msg, 点击pos:%d,%d \ n, xPos,yPos);
SetDlgItemText(hwndDlg,IDC_CLICKPOS_OUTPUT,msg);
break ;
}
}
return TRUE;
}
return FALSE;
}


int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nShowCmd)
{
hInst = hInstance;
InitCommonControls();
IMGWINDOW_Register();
return DialogBox(hInst,MAKEINTRESOURCE(DLG_MAIN),NULL,(DLGPROC)DlgMain);
}





resource.h

  #ifndef IDC_STATIC 
#define IDC_STATIC(-1)
#endif

#define DLG_MAIN 100
#define IDC_CLICKPOS_OUTPUT 40000
#define IDC_IMAGE_WINDOW 40001





resource.rc

  //  由ResEdit 1.6.2生成 
// 版权所有(C)2006-2014
// http://www.resedit。 net
#include < windows.h >
#include < commctrl.h >
#include < richedit.h >
#include resource.h

//
// 对话资源
//
LANGUAG E LANG_NEUTRAL,SUBLANG_NEUTRAL
DLG_MAIN对话 0 0 185 166
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
CAPTION 对话框
FONT 8 Shell Dlg女士
{
LTEXT ,IDC_CLICKPOS_OUTPUT, 7 151 171 8 ,SS_LEFT, WS_EX_LEFT
CONTROL ,IDC_IMAGE_WINDOW, imgWindow32,0x50020000, 7 7 171 139 ,0x00000000
}









最后,这里是图像显示和clic的肉和骨头k-pos计算。

再次,即使有点冗长也很简单。

imgWindow.h

< pre lang =c ++> #ifndef imgWindow_h
#define imgWindow_h

#include < windows.h >

// 外部可调用函​​数
//
BOOL IMGWINDOW_Register();
void IMGWINDOW_Unregister();


// 窗口类名定义
//
#define IMGWINDOW_CLASSAimgWindow32
#define IMGWINDOW_CLASSW LimgWindow32

#ifdef UNICODE
#define IMGWINDOW_CLASS IMGWINDOW_CLASSW
#else
#define IMGWINDOW_CLASS IMGWINDOW_CLASSA
#endif // UNICODE


// 此类的可用用户定义消息
//
#define IM_SETIMAGE WM_USER + 1
#define IM_GETCLICKPOS WM_USER + 2

// 用于使用上面定义的消息与控件交互的宏
//
#define ImageWindow_SetImage(hWnd,hBitmap)SendMessage(hWnd,IM_SETIMAGE,0,(LPARAM)hBitmap)
#define ImageWindow_GetClickPos(hWnd)SendMessage(hWnd,IM_GETCLICKPOS,0,0)

#endif // imgWindow_h







imgWindow.cpp

  #include     imgWindow.h 

#ifndef min
#define min(a,b)a< b? a:b
#endif // min

typedef struct
{
HWND self;
clickX,点击Y;
BOOL mouseDown;
int xScrollPos,yScrollPos;
int xImgOfs,yImgOfs;
HBITMAP bkg;
HDC memDC;
HBITMAP oldMemBmp;
int bmpWidth,bmpHeight;
RECT clientRect;
} IMGWINDOW_INFO;


#define IMGWINDOW_GetInfoPtr(hWindow)((IMGWINDOW_INFO *)GetWindowLongPtr(hWindow,0))


int onImgWindowCreate(HWND hwnd,WPARAM wParam,LPARAM lParam)
{
IMGWINDOW_INFO * infoPtr =(IMGWINDOW_INFO *)LocalAlloc (LPTR, sizeof (IMGWINDOW_INFO));
if (!infoPtr)
return - 1 ;

ZeroMemory(infoPtr, sizeof (infoPtr));
infoPtr-> self = hwnd;

infoPtr-> clickX = - 1 ;
infoPtr-> clickY = - 1 ;

HDC mDC;
mDC = GetDC(hwnd);
infoPtr-> memDC = CreateCompatibleDC(mDC);
infoPtr-> oldMemBmp =(HBITMAP)GetCurrentObject(infoPtr-> memDC,OBJ_BITMAP);
ReleaseDC(hwnd,mDC);

GetClientRect(hwnd,& infoPtr-> clientRect);

SetWindowLong(hwnd, 0 ,(LONG)infoPtr); // 此处可能出现x64问题//
返回 0 ;
}

int onImgWindowDestroy(HWND hwnd)
{
IMGWINDOW_INFO * infoPtr =(IMGWINDOW_INFO *) LocalAlloc(LPTR, sizeof (IMGWINDOW_INFO));
SelectObject(infoPtr-> memDC,infoPtr-> oldMemBmp);
DeleteDC(infoPtr-> memDC);
LocalFree(infoPtr);
return 0 ;
}

int onImgWindowEraseBackground(HWND hwnd,WPARAM wParam,LPARAM lParam)
{
RECT clientRect ;
HBRUSH bkBrush;
IMGWINDOW_INFO * infoPtr = IMGWINDOW_GetInfoPtr(hwnd);
bkBrush = CreateSolidBrush(RGB( 255 0 255 ));
GetClientRect(hwnd,& clientRect);
FillRect((HDC)wParam,& clientRect,bkBrush);
DeleteObject(bkBrush);
return 1 ;
}

int doImgWindowScroll(HWND hwnd,WPARAM wParam, int orientation, int windowMin, int windowMax)
{
int windowSize = windowMax - windowMin + 1 ;
switch (LOWORD(wParam))
{
case SB_THUMBTRACK :
SetScrollPos(hwnd,orientation,HIWORD(wParam), true );
break ;

case SB_PAGERIGHT:
SetScrollPos(hwnd,orientation,GetScrollPos(hwnd,orientation)+ windowSize,);
break ;

case SB_PAGELEFT:
SetScrollPos(hwnd,orientation,GetScrollPos(hwnd,orientation)-windowSize,);
break ;

case SB_LINELEFT:
SetScrollPos(hwnd,orientation,GetScrollPos(hwnd,orientation) - 16 true );
break ;

case SB_LINERIGHT:
SetScrollPos(hwnd,orientation,GetScrollPos(hwnd,orientation)+16,);
break ;
}
IMGWINDOW_INFO * mData = IMGWINDOW_GetInfoPtr(hwnd);
int scrollPos = GetScrollPos(hwnd,orientation);
if (orientation == SB_HORZ)
mData-> xScrollPos = scrollPos;
else if (orientation == SB_VERT)
mData-> yScrollPos = scrollPos;

InvalidateRect(hwnd,NULL, true );
return 0 ;
}


int onImgWindowHscroll(HWND hwnd,WPARAM wParam,LPARAM lParam)
{
RECT clientRect;
GetClientRect(hwnd,& clientRect);
return doImgWindowScroll(hwnd,wParam,SB_HORZ,clientRect.left,clientRect.right);
}

int onImgWindowVscroll(HWND hwnd,WPARAM wParam,LPARAM lParam)
{
RECT clientRect ;
GetClientRect(hwnd,& clientRect);
return doImgWindowScroll(hwnd,wParam,SB_VERT,clientRect.top,clientRect.bottom);
}

void imgWindowSetScrollInfo(HWND hwnd)
{
int mWidth;
RECT mRect;
SCROLLINFO si = {};

IMGWINDOW_INFO * infoPtr = IMGWINDOW_GetInfoPtr(hwnd);

GetClientRect(hwnd,& mRect);
mWidth = mRect.right - mRect.left + 1 ;

si.cbSize = sizeof (si);
si.fMask = SIF_ALL;
si.nMin = 0 ;
si.nMax = infoPtr-> bmpWidth; // - mWidth; // - mWidth;
si.nPage = mWidth;
si.nPos = 0 ;
infoPtr-> xScrollPos = 0 ;
SetScrollInfo(hwnd,SB_HORZ,& si, false );

int mHeight;
mHeight = mRect.bottom-mRect.top + 1 ;
si.cbSize = sizeof (si);
si.fMask = SIF_ALL;
si.nMin = 0 ;
si.nMax = infoPtr-> bmpHeight; // - mHeight;
si.nPage = mHeight;
si.nPos = 0 ;
infoPtr-> yScrollPos = 0 ;
SetScrollInfo(hwnd,SB_VERT,& si, true );
}

LRESULT onImgWindowSetImage(HWND hwnd,WPARAM wParam,LPARAM lParam)
{
IMGWINDOW_INFO * infoPtr =(IMGWINDOW_INFO *)GetWindowLongPtr(hwnd, 0 );

HBITMAP oldImg;
oldImg = infoPtr-> bkg;
infoPtr-> bkg =(HBITMAP)lParam;

BITMAP bm;
GetObject(infoPtr-> bkg, sizeof (bm),& bm);
infoPtr-> bmpWidth = bm.bmWidth;
infoPtr-> bmpHeight = bm.bmHeight;

if (infoPtr-> bmpWidth>(infoPtr-> clientRect.right-infoPtr-> clientRect.left))
ShowScrollBar(hwnd,SB_HORZ, true );
else
ShowScrollBar(hwnd,SB_HORZ, false );

if (infoPtr-> bmpHeight>(infoPtr-> clientRect.bottom-infoPtr-> clientRect.top))
ShowScrollBar(hwnd,SB_VERT, true );
else
ShowScrollBar(hwnd,SB_VERT, false );

imgWindowSetScrollInfo(hwnd);

SelectObject(infoPtr-> memDC,infoPtr-> bkg);
InvalidateRect(infoPtr-> self,NULL, true );
return (LRESULT)oldImg;
}


// 窗口的背景淡入淡出
LRESULT CALLBACK IMGWINDOW_WindowProc(HWND hwnd,UINT消息,WPARAM wParam,LPARAM lParam)
{
IMGWINDOW_INFO * infoPtr =(IMGWINDOW_INFO *)GetWindowLongPtr(hwnd, 0 );

switch (消息) // 处理消息
{
case WM_CREATE:
return onImgWindowCreate(hwnd,wParam,lParam);

case WM_DESTROY:
return onImgWindowDestroy(hwnd);

// lParam =(HBITMAP)img
case IM_SETIMAGE:
return onImgWindowSetImage(hwnd,wParam,lParam);

case WM_ERASEBKGND:
return onImgWindowEraseBackground(hwnd,wParam, LPARAM);

case WM_PAINT:
HDC hdc;
PAINTSTRUCT ps;
int mWidth,mHeight;
RECT mRect;
GetClientRect(hwnd,& mRect);
mWidth = mRect.right-mRect.left + 1 ;
mHeight = mRect.bottom-mRect.top + 1 ;
hdc = BeginPaint(hwnd,& ps);

int xOfs,yOfs;
xOfs = yOfs = 0 ;

if (infoPtr-> bmpWidth< mWidth)
xOfs =(mWidth-infoPtr-> bmpWidth)/ 2 ;

if (infoPtr-> bmpHeight< mHeight)
yOfs =(mHeight-infoPtr-> bmpHeight)/ 2 ;
infoPtr-> xImgOfs = xOfs;
infoPtr-> yImgOfs = yOfs;


int drawWidth,drawHeight;
drawWidth = min(infoPtr-> bmpWidth,mWidth);
drawHeight = min(infoPtr-> bmpHeight,mHeight);

int imgXofs,imgYofs;
imgXofs = infoPtr-> xScrollPos;
imgYofs = infoPtr-> yScrollPos;
BitBlt(
hdc,
xOfs,yOfs,
drawWidth,drawHeight,
infoPtr-> memDC,
imgXofs,imgYofs,
SRCCOPY);

EndPaint(hwnd,& ps);
return 0 ;

case WM_HSCROLL:
return onImgWindowHscroll(hwnd,wParam, LPARAM);

case WM_VSCROLL:
return onImgWindowVscroll(hwnd,wParam, LPARAM);

case WM_SIZE:
GetClientRect(hwnd,& infoPtr-> clientRect);
InvalidateRect(hwnd,NULL, true );
return 0 ;

case WM_GETDLGCODE:
return DLGC_STATIC;

case WM_LBUTTONDOWN:
infoPtr-> mouseDown = true ;
return 0 ;

case WM_LBUTTONUP:
{
// 保存准备使用的点以响应IM_GETCLICKPOS消息
infoPtr-> clickX =( short )(LOWORD(lParam)+ infoPtr-> xScrollPos - infoPtr-> xImgOfs);
infoPtr-> clickY =( short )(HIWORD(lParam)+ infoPtr-> yScrollPos - infoPtr-> yImgOfs);

// 告诉paent窗口我们点击了WM_COMMAND消息
short myNotifIdCode = 0 ;
if (infoPtr-> mouseDown == true
SendMessage(GetParent (infoPtr-> self),WM_COMMAND,MAKEWPARAM(GetDlgCtrlID(infoPtr-> self),myNotifIdCode),(LPARAM)infoPtr-> self);
}
infoPtr-> mouseDown = false ;
break ;

case IM_GETCLICKPOS:
return MAKELPARAM(infoPtr-> clickX,infoPtr-> clickY);
}
return DefWindowProc(hwnd,message,wParam,lParam);
}


BOOL IMGWINDOW_Register( void
{
WNDCLASS wndClass;

ZeroMemory(& wndClass, sizeof (WNDCLASS));
wndClass.style = CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW | CS_OWNDC; // CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS;
wndClass.lpfnWndProc = IMGWINDOW_WindowProc;
wndClass.cbClsExtra = 0 ;
wndClass.cbWndExtra = sizeof (IMGWINDOW_INFO *); // 通过getwindowlong(hWnd,nIndex)访问
wndClass.hCursor = LoadCursor( 0 ,IDC_ARROW);
wndClass.hbrBackground = 0 ;
wndClass.lpszClassName = IMGWINDOW_CLASS;

if (RegisterClass(& wndClass)!= 0
返回 true ;
else
return false < /跨度>;
}

void IMGWINDOW_Unregister( void
{
UnregisterClass(IMGWINDOW_CLASS,NULL);
}


感谢您的澄清。这里有一切都很好描述: https:// msdn。 microsoft.com/en-us/library/windows/desktop/ms645533%28v=vs.85%29.aspx [ ^ ]。



样品?这不会太难,但谁会花这么多时间?我们谁会浪费这么多时间用纯粹的C.写作。为什么?很少有简单的练习可以用来学习,但是仔细地将所有大象联系起来...... :-)



怎么样:你阅读文档并尝试编写代码,询问遇到问题时会另外提出问题吗?



-SA


在Visual Basic中它太容易了。

将来我会在VB中编写windows元素,并且代码必须更快。在C中作为dll
。我从谷歌获得的所有信息。



 公共  MyCalcHelp 
公共 allstr 作为 字符串 =
公开 tmpstr 作为 字符串 =
公开 mytext As 字符串 =
公共计数器作为 整数 = < span class =code-digit> 0


私人 Sub MyCalcHelp_KeyUp( ByVal sender As Object ByVal e As System.Windows.Forms.KeyEventArgs)句柄 .KeyUp
如果 e .KeyValue = Keys.Escape 然后
应用程序。退出()
结束 如果

如果 e.KeyValue = Keys.Enter tmpstr<> \"\" Then
allstr = allstr & tmpstr
'MessageBox.Show(Me.Top.ToString)
tmpstr = \"\"

If counter = 0 Then
mytext = \"question1\"
TextBox1.Text = mytext
counter += 1
ElseIf counter = 1 Then
mytext = \"question2\"
TextBox1.Text = mytext
counter += 1
ElseIf c ounter = 2 Then
mytext = \"question3\"
TextBox1.Text = mytext
counter += 1
ElseIf counter = 3 Then
mytext = \"question4\"
TextBox1.Text = mytext
counter += 1
End If
End If
End Sub


Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
For Each argument As String In My.Application.CommandLineArgs
PictureBox1.ImageLocation = argument
Exit For
Next

Me.WindowState = FormWindowState.Maximized
Panel1.Width = Me.Width
Panel1.Top = Me.Top + 12
Panel1.Height = Me.Height
Panel1.Left = Me.Left + 12

TextBox1.Text = \"Starting...\"

If counter = 0 Then
mytext = \"question1\"
TextBox1.Text = mytext
counter += 1
End If
End Sub

Private Sub PictureBox1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PictureBox1.Click
Dim ScreenPos As Point = PictureBox1.PointToScreen(New Point(0, 0))
tmpstr = Control.MousePosition().X.ToString & \" \" & Control.MousePosition().Y.ToString & vbCrLf
TextBox1.Text = mytext & & tmpstr
MessageBox.Show(ScreenPos.X.ToString & \" \" & ScreenPos.Y.ToString)
End Sub

Private Sub TextBox1_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles TextBox1.MouseMove
If TextBox1.Location.Y = 0 Then
TextBox1.Location = New Point(10, 200)
Else
TextBox1.Location = New Point(10, 0)
End If
End Sub

End Class


I need some help with window api 32 bit programming in C with Visual C++ 2008.

Load a picture path/filename from command line in a window.
But if it is bigger with working scrollbars.
A mouseclick give the xy of the picture not from the window client area.

Has anyone an advice or example ?

解决方案

I had a bit of spare time this evening while waiting for someone, so decided to have a bit of a play. I haven't bothered with error checking, you should add that yourself. I've also elected to program in a style similar to the one MS used when programming many of the different window-classes, as found in portions of the (re-engineered) Wine project. (https://github.com/wine-mirror/wine/tree/master/dlls/comctl32[^])

I've tried to make it very simple to interact with.

First, you must register the class - you can do this during program startup, before anything is shown on the screen.

Next, the two messages I've defined. IM_SETIMAGE and IM_GETCLICKPOS. You can send these messages explicitly, or you can use the supplied macros.
If you elect to send these messages yourself, you need only know:

IM_SETIMAGE expects the lParam to hold the HBITMAP of the new image. The return value is the previous image (if any, NULL otherwise)

IM_GETCLICKPOS takes no parameters and returns the position within the image of the last click pos (you get notified of clicks through a WM_COMMAND message). The lo-order word contains the X position and the hi-order word contains the Y position. Positions to the left/above the image return negative values.

The background colour isn't customizable from within the containing application, though you could easily add code to handle this situation, or more simply, edit the function onImgWindowEraseBackground.

The code's far from perfect, but should help provide a good starting point. You'll still have a bit of work. While you mention passing the name of a file to the program in order to choose the image, I'd suggest that you approach this with a little more sophistication and create a 'config' file of sorts. In this file, you could include things like (1) the name of the image file (2) the number of areas of interest (3) co-ordinate pairs for the points of a polygon that enclose these areas.

Perhaps something like this:
------------config.txt------------
Image: image.bmp
Poly Count: 3
Apple: 10,10, 20,10, 20,20, 10,20
Water Melon: 100,100, 200,100, 200,200, 100,200
Triangle: 50,50, 75,75, 25,75
----------------------------------


For a basic example of use, I've thrown-together the following dialog app. (written with Code::Blocks, built with MinGW)

main.cpp

#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include "resource.h"
#include "../scrollImage/imgWindow.h"

HINSTANCE hInst;

BOOL CALLBACK DlgMain(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
        case WM_INITDIALOG:
        {
            HBITMAP img;
            img = (HBITMAP)LoadImage(hInst, "image.bmp", IMAGE_BITMAP, 0,0, LR_LOADFROMFILE);
            ImageWindow_SetImage( GetDlgItem(hwndDlg, IDC_IMAGE_WINDOW), img);
        }
        return TRUE;

        case WM_CLOSE:
        {
            EndDialog(hwndDlg, 0);
        }
        return TRUE;

        case WM_COMMAND:
        {
            switch(LOWORD(wParam))
            {
                case IDC_IMAGE_WINDOW:
                    LPARAM clickPos = ImageWindow_GetClickPos( (HWND)lParam );
                    short xPos = LOWORD(clickPos);
                    short yPos = HIWORD(clickPos);
                    char msg[32];
                    sprintf(msg, "Click pos: %d,%d\n", xPos, yPos);
                    SetDlgItemText(hwndDlg, IDC_CLICKPOS_OUTPUT, msg);
                    break;
            }
        }
        return TRUE;
    }
    return FALSE;
}


int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    hInst=hInstance;
    InitCommonControls();
    IMGWINDOW_Register();
    return DialogBox(hInst, MAKEINTRESOURCE(DLG_MAIN), NULL, (DLGPROC)DlgMain);
}



resource.h

#ifndef IDC_STATIC
#define IDC_STATIC (-1)
#endif

#define DLG_MAIN                                100
#define IDC_CLICKPOS_OUTPUT                     40000
#define IDC_IMAGE_WINDOW                        40001



resource.rc

// Generated by ResEdit 1.6.2
// Copyright (C) 2006-2014
// http://www.resedit.net
#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#include "resource.h"

//
// Dialog resources
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
DLG_MAIN DIALOG 0, 0, 185, 166
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
CAPTION "Dialog"
FONT 8, "Ms Shell Dlg"
{
    LTEXT           "", IDC_CLICKPOS_OUTPUT, 7, 151, 171, 8, SS_LEFT, WS_EX_LEFT
    CONTROL         "", IDC_IMAGE_WINDOW, "imgWindow32", 0x50020000, 7, 7, 171, 139, 0x00000000
}





Finally, here's the meat and bones of the image display and click-pos calculation.
Again, quite simple even if a little lengthy.
imgWindow.h

#ifndef imgWindow_h
    #define imgWindow_h

#include <windows.h>

// externably callable functions
//
BOOL IMGWINDOW_Register();
void IMGWINDOW_Unregister();


// window class-name definitions
//
#define IMGWINDOW_CLASSA "imgWindow32"
#define IMGWINDOW_CLASSW L"imgWindow32"

#ifdef UNICODE
    #define IMGWINDOW_CLASS IMGWINDOW_CLASSW
#else
    #define IMGWINDOW_CLASS IMGWINDOW_CLASSA
#endif // UNICODE


// available user-defined messages for this class
//
#define IM_SETIMAGE     WM_USER + 1
#define IM_GETCLICKPOS  WM_USER + 2

// macros for interacting with the control using the above-defined messages
//
#define ImageWindow_SetImage(hWnd, hBitmap) SendMessage(hWnd, IM_SETIMAGE, 0, (LPARAM)hBitmap)
#define ImageWindow_GetClickPos(hWnd) SendMessage(hWnd, IM_GETCLICKPOS, 0, 0)

#endif // imgWindow_h




imgWindow.cpp

#include "imgWindow.h"

#ifndef min
    #define min(a,b) a < b ? a : b
#endif // min

typedef struct
{
    HWND self;
    short  clickX, clickY;
    BOOL mouseDown;
    int xScrollPos, yScrollPos;
    int xImgOfs, yImgOfs;
    HBITMAP bkg;
    HDC memDC;
    HBITMAP oldMemBmp;
    int bmpWidth, bmpHeight;
    RECT clientRect;
} IMGWINDOW_INFO;


#define IMGWINDOW_GetInfoPtr(hWindow) ((IMGWINDOW_INFO *)GetWindowLongPtr (hWindow, 0))


int onImgWindowCreate(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
    IMGWINDOW_INFO *infoPtr = (IMGWINDOW_INFO*)LocalAlloc(LPTR, sizeof(IMGWINDOW_INFO));
    if (!infoPtr)
        return -1;

    ZeroMemory(infoPtr, sizeof(infoPtr));
    infoPtr->self = hwnd;

    infoPtr->clickX = -1;
    infoPtr->clickY = -1;

    HDC mDC;
    mDC = GetDC(hwnd);
    infoPtr->memDC = CreateCompatibleDC(mDC);
    infoPtr->oldMemBmp = (HBITMAP) GetCurrentObject(infoPtr->memDC, OBJ_BITMAP);
    ReleaseDC(hwnd, mDC);

    GetClientRect(hwnd, &infoPtr->clientRect);

    SetWindowLong(hwnd, 0, (LONG)infoPtr);      // possible x64 problem here //
    return 0;
}

int onImgWindowDestroy(HWND hwnd)
{
    IMGWINDOW_INFO *infoPtr = (IMGWINDOW_INFO*)LocalAlloc(LPTR, sizeof(IMGWINDOW_INFO));
    SelectObject(infoPtr->memDC, infoPtr->oldMemBmp);
    DeleteDC( infoPtr->memDC );
    LocalFree(infoPtr);
    return 0;
}

int onImgWindowEraseBackground(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
    RECT clientRect;
    HBRUSH bkBrush;
    IMGWINDOW_INFO *infoPtr = IMGWINDOW_GetInfoPtr(hwnd);
    bkBrush = CreateSolidBrush( RGB(255,0,255) );
    GetClientRect(hwnd, &clientRect);
    FillRect( (HDC)wParam, &clientRect, bkBrush);
    DeleteObject(bkBrush);
    return 1;
}

int doImgWindowScroll(HWND hwnd, WPARAM wParam, int orientation, int windowMin, int windowMax)
{
    int windowSize = windowMax - windowMin + 1;
    switch (LOWORD(wParam))
    {
        case SB_THUMBTRACK:
            SetScrollPos(hwnd, orientation, HIWORD(wParam), true);
            break;

        case SB_PAGERIGHT:
            SetScrollPos(hwnd, orientation, GetScrollPos(hwnd, orientation)+windowSize, true);
            break;

        case SB_PAGELEFT:
            SetScrollPos(hwnd, orientation, GetScrollPos(hwnd, orientation)-windowSize, true);
            break;

        case SB_LINELEFT:
            SetScrollPos(hwnd, orientation, GetScrollPos(hwnd, orientation)-16, true);
            break;

        case SB_LINERIGHT:
            SetScrollPos(hwnd, orientation, GetScrollPos(hwnd, orientation)+16, true);
            break;
    }
    IMGWINDOW_INFO *mData = IMGWINDOW_GetInfoPtr(hwnd);
    int scrollPos = GetScrollPos(hwnd, orientation);
    if (orientation == SB_HORZ)
        mData->xScrollPos = scrollPos;
    else if (orientation == SB_VERT)
        mData->yScrollPos = scrollPos;

    InvalidateRect(hwnd, NULL, true);
    return 0;
}


int onImgWindowHscroll(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
    RECT clientRect;
    GetClientRect(hwnd, &clientRect);
    return doImgWindowScroll(hwnd, wParam, SB_HORZ, clientRect.left, clientRect.right);
}

int onImgWindowVscroll(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
    RECT clientRect;
    GetClientRect(hwnd, &clientRect);
    return doImgWindowScroll(hwnd, wParam, SB_VERT, clientRect.top, clientRect.bottom);
}

void imgWindowSetScrollInfo(HWND hwnd)
{
    int mWidth;
    RECT mRect;
    SCROLLINFO si = {};

    IMGWINDOW_INFO *infoPtr = IMGWINDOW_GetInfoPtr(hwnd);

    GetClientRect(hwnd, &mRect);
    mWidth = mRect.right - mRect.left + 1;

    si.cbSize = sizeof(si);
    si.fMask = SIF_ALL;
    si.nMin = 0;
    si.nMax = infoPtr->bmpWidth;// - mWidth;// - mWidth;
    si.nPage = mWidth;
    si.nPos = 0;
    infoPtr->xScrollPos = 0;
    SetScrollInfo(hwnd, SB_HORZ, &si, false);

    int mHeight;
    mHeight = mRect.bottom-mRect.top + 1;
    si.cbSize = sizeof(si);
    si.fMask = SIF_ALL;
    si.nMin = 0;
    si.nMax = infoPtr->bmpHeight;// - mHeight;
    si.nPage = mHeight;
    si.nPos = 0;
    infoPtr->yScrollPos = 0;
    SetScrollInfo(hwnd, SB_VERT, &si, true);
}

LRESULT onImgWindowSetImage(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
    IMGWINDOW_INFO *infoPtr = (IMGWINDOW_INFO *)GetWindowLongPtr(hwnd, 0);

    HBITMAP oldImg;
    oldImg = infoPtr->bkg;
    infoPtr->bkg = (HBITMAP) lParam;

    BITMAP bm;
    GetObject(infoPtr->bkg, sizeof(bm), &bm);
    infoPtr->bmpWidth = bm.bmWidth;
    infoPtr->bmpHeight = bm.bmHeight;

    if (infoPtr->bmpWidth > (infoPtr->clientRect.right-infoPtr->clientRect.left) )
        ShowScrollBar(hwnd, SB_HORZ, true);
    else
        ShowScrollBar(hwnd, SB_HORZ, false);

    if (infoPtr->bmpHeight > (infoPtr->clientRect.bottom-infoPtr->clientRect.top) )
        ShowScrollBar(hwnd, SB_VERT, true);
    else
        ShowScrollBar(hwnd, SB_VERT, false);

    imgWindowSetScrollInfo(hwnd);

    SelectObject(infoPtr->memDC, infoPtr->bkg);
    InvalidateRect(infoPtr->self, NULL, true);
    return (LRESULT)oldImg;
}


// window's background fades-in when hovered
LRESULT CALLBACK IMGWINDOW_WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    IMGWINDOW_INFO *infoPtr = (IMGWINDOW_INFO *)GetWindowLongPtr(hwnd, 0);

    switch (message)                  // handle the messages
    {
        case WM_CREATE:
            return onImgWindowCreate(hwnd, wParam, lParam);

        case WM_DESTROY:
            return onImgWindowDestroy(hwnd);

        // lParam = (HBITMAP) img
        case IM_SETIMAGE:
            return onImgWindowSetImage(hwnd, wParam, lParam);

        case WM_ERASEBKGND:
            return onImgWindowEraseBackground(hwnd, wParam, lParam);

        case WM_PAINT:
            HDC hdc;
            PAINTSTRUCT ps;
            int mWidth, mHeight;
            RECT mRect;
            GetClientRect(hwnd, &mRect);
            mWidth = mRect.right-mRect.left + 1;
            mHeight = mRect.bottom-mRect.top + 1;
            hdc = BeginPaint(hwnd, &ps);

            int xOfs,yOfs;
            xOfs = yOfs = 0;

            if (infoPtr->bmpWidth < mWidth)
                xOfs = (mWidth-infoPtr->bmpWidth)/2;

            if (infoPtr->bmpHeight < mHeight)
                yOfs = (mHeight-infoPtr->bmpHeight)/2;
            infoPtr->xImgOfs = xOfs;
            infoPtr->yImgOfs = yOfs;


            int drawWidth, drawHeight;
            drawWidth = min(infoPtr->bmpWidth, mWidth);
            drawHeight = min(infoPtr->bmpHeight, mHeight);

            int imgXofs, imgYofs;
            imgXofs = infoPtr->xScrollPos;
            imgYofs = infoPtr->yScrollPos;
            BitBlt(
                    hdc,
                    xOfs, yOfs,
                    drawWidth,drawHeight,
                    infoPtr->memDC,
                    imgXofs,imgYofs,
                    SRCCOPY);

            EndPaint(hwnd, &ps);
            return 0;

        case WM_HSCROLL:
            return onImgWindowHscroll(hwnd, wParam, lParam);

        case WM_VSCROLL:
            return onImgWindowVscroll(hwnd, wParam, lParam);

        case WM_SIZE:
            GetClientRect(hwnd, &infoPtr->clientRect);
            InvalidateRect(hwnd, NULL, true);
            return 0;

        case WM_GETDLGCODE:
            return DLGC_STATIC;

        case WM_LBUTTONDOWN:
            infoPtr->mouseDown = true;
            return 0;

        case WM_LBUTTONUP:
            {
                // save the point ready to use in response to the IM_GETCLICKPOS message
                infoPtr->clickX = (short)(LOWORD(lParam) + infoPtr->xScrollPos - infoPtr->xImgOfs);
                infoPtr->clickY = (short)(HIWORD(lParam) + infoPtr->yScrollPos - infoPtr->yImgOfs);

                // tell the paent window that we were clicked with a WM_COMMAND message
                short myNotifIdCode = 0;
                if (infoPtr->mouseDown == true)
                    SendMessage(GetParent(infoPtr->self), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(infoPtr->self),myNotifIdCode), (LPARAM)infoPtr->self);
            }
            infoPtr->mouseDown = false;
            break;

        case IM_GETCLICKPOS:
            return MAKELPARAM(infoPtr->clickX, infoPtr->clickY);
    }
    return DefWindowProc (hwnd, message, wParam, lParam);
}


BOOL IMGWINDOW_Register(void)
{
    WNDCLASS wndClass;

    ZeroMemory (&wndClass, sizeof(WNDCLASS));
    wndClass.style         = CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW | CS_OWNDC;//CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS;
    wndClass.lpfnWndProc   = IMGWINDOW_WindowProc;
    wndClass.cbClsExtra    = 0;
    wndClass.cbWndExtra    = sizeof(IMGWINDOW_INFO *);   // accessed via getwindowlong(hWnd, nIndex)
    wndClass.hCursor       = LoadCursor(0, IDC_ARROW);
    wndClass.hbrBackground = 0;
    wndClass.lpszClassName = IMGWINDOW_CLASS;

    if (RegisterClass(&wndClass) != 0)
        return true;
    else
        return false;
}

void IMGWINDOW_Unregister(void)
{
    UnregisterClass(IMGWINDOW_CLASS, NULL);
}


Thank you for the clarification. Everything is well described here: https://msdn.microsoft.com/en-us/library/windows/desktop/ms645533%28v=vs.85%29.aspx[^].

Samples? It would not be too hard, but who will spend so much time? Who of us would waste so much time for writing it all in pure C. Why? Few simple exercises could be useful for learning, but meticulously baying all those elephants… :-)

How about this: you read the documentation and try to write code, ask separate questions when you face problems?

—SA


In Visual Basic it is sooooo easy.
In future I will write windows elements in VB and code that must be faster
in C as dll. All infos I get from google.

Public Class MyCalcHelp
    Public allstr As String = ""
    Public tmpstr As String = ""
    Public mytext As String = ""
    Public counter As Integer = 0


    Private Sub MyCalcHelp_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyUp
        If e.KeyValue = Keys.Escape Then
            Application.Exit()
        End If

        If e.KeyValue = Keys.Enter And tmpstr <> "" Then
            allstr = allstr & tmpstr
            'MessageBox.Show(Me.Top.ToString)
            tmpstr = ""

            If counter = 0 Then
                mytext = "question1"
                TextBox1.Text = mytext
                counter += 1
            ElseIf counter = 1 Then
                mytext = "question2"
                TextBox1.Text = mytext
                counter += 1
            ElseIf counter = 2 Then
                mytext = "question3"
                TextBox1.Text = mytext
                counter += 1
            ElseIf counter = 3 Then
                mytext = "question4"
                TextBox1.Text = mytext
                counter += 1
            End If
        End If
    End Sub


    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        For Each argument As String In My.Application.CommandLineArgs
            PictureBox1.ImageLocation = argument
            Exit For
        Next

        Me.WindowState = FormWindowState.Maximized
        Panel1.Width = Me.Width
        Panel1.Top = Me.Top + 12
        Panel1.Height = Me.Height
        Panel1.Left = Me.Left + 12

        TextBox1.Text = "Starting..."

        If counter = 0 Then
            mytext = "question1"
            TextBox1.Text = mytext
            counter += 1
        End If
    End Sub

    Private Sub PictureBox1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PictureBox1.Click
        Dim ScreenPos As Point = PictureBox1.PointToScreen(New Point(0, 0))
        tmpstr = Control.MousePosition().X.ToString & " " & Control.MousePosition().Y.ToString & vbCrLf
        TextBox1.Text = mytext & "  " & tmpstr
        MessageBox.Show(ScreenPos.X.ToString & "  " & ScreenPos.Y.ToString)
    End Sub

    Private Sub TextBox1_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles TextBox1.MouseMove
        If TextBox1.Location.Y = 0 Then
            TextBox1.Location = New Point(10, 200)
        Else
            TextBox1.Location = New Point(10, 0)
        End If
    End Sub

End Class


这篇关于加载图片可滚动&amp;鼠标点击时获取x,y的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆