프로그래밍 관련/MFC

비쥬얼스튜디오 Visual Studio GDIPLUS 이미지 처리 관련

AlrepondTech 2017. 3. 21. 14:54
반응형

 

 

 

 

=======================

=======================

=======================

 

 

 

 

 

주의

 

Image::FromFile(파일경로이름)

 

Bitmap::FromFile(파일경로이름)

 

 

이 함수를 쓸대 파일경로이름 문자열을  (WCHAR*)L"파일경로이름" 이렇게 처리해주어야

파일을 제대로 찾는다

 

Visual Studio 2017 버전을 쓰는데 "L" 자를 뺴먹어서 파일을 찾지를 못해 애먹은적이 있다.

 

 

 

=======================

=======================

=======================

 

 

 

 

출처: 

 

 

일반적으로 배우는 Win32API에서 이미지 출력은 BMP파일을 리소스에 등록하여 LoadImage함수로 핸들을 받아와 Bitblt 하는 방법을 사용한다. 비트맵에 배경값을 지우는 transparentblt함수등이 있지만 PNG파일은 사용할 수 없다..

 

GDI+를 사용하면 다음과 같은 포맷을 기본적으로 사용가능하다

 

BMP

GIF

JPEG

PNG

TIFF

 

사용하는 방법도 크게 어렵지 않다.

 

// 헤더 추가

#include <gdiplus.h>

using namespace Gdiplus;

 

 // 링커 추가

#pragma comment(lib, "Gdiplus.lib")

 

// 초기화

ULONG_PTR gdiplusToken; // 마지막에 GdiplusShutdown에서 사용하므로 저장필수.

 

GdiplusStartupInput gdiplusStartupInput;

GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

 

//이미지 불러오기

Image* image = Image::FromFile(L"image..png"); // 같은 폴더내에 image.png 파일을 불러옴.

 

//그리기

Graphics g( [hdc] );      // Bitblt에서 사용하던 그 hdc를 넣으면 됨.

g.DrawImage(image, [x], [y]);  // x, y좌표 외에도 width ,height를 받는 등의 오버로딩된 함수가 많다.

 

//해제

delete image;

GdiplusShutdown(gdiplusToken);

 

이미지를 불러오는 과정에서 FromFile은 외부경로를 통해 읽어오므로 이미지파일이 같은 폴더안에 있어야 한다.

(즉 .exe파일과 .png파일이 같은 폴더에 있어야함. 또한 프로그램 실행중 .png파일의 수정 불가능.)

 

리소스를 통해 불러오는 방법은 다음 포스팅에 이어서...

 

 

 

 

 

 

=======================

=======================

=======================

 

 

 

 

 

출처: https://msdn.microsoft.com/ko-kr/library/4sahykhd(v=vs.110).aspx

 

Image::FromFile 메서드 (String^, Boolean)

.NET Framework (current version)
 
다른 버전
 
 

게시 날짜: 2016년 11월

만듭니다는 Image 지정된 된 파일에서 사용 하 여 색 관리 정보 파일에 포함 된 해당 합니다.

네임스페이스:   System.Drawing
어셈블리:  System.Drawing(System.Drawing.dll에 있음)

구문
 
 
public: static Image^ FromFile( 	String^ filename, 	bool useEmbeddedColorManagement ) 

매개 변수

filename
Type: System::String^

작성 하려는 파일의 이름을 포함 하는 문자열은 Image합니다.

useEmbeddedColorManagement
Type: System::Boolean

로 설정 true 이미지 파일에 포함 된 색 관리 정보를 사용 하 여 그렇지 false합니다.

반환 값

Type: System.Drawing::Image^

이 메서드가 만드는 Image입니다.

예외
 
Exception Condition
OutOfMemoryException
파일에 올바른 이미지 형식이 없는지 않습니다.
또는
GDI+ 파일의 픽셀 형식을 지원 하지 않습니다.
FileNotFoundException
지정한 파일이 존재 하지 않습니다.
ArgumentException
filename 한 Uri합니다.
설명
 

관리 GDI + 기본 제공 인코더 및 디코더는 다음 파일 형식을 지 원하는 있습니다.

  • BMP
  • GIF
  • JPEG
  • PNG
  • TIFF

파일에 올바른 이미지 형식이 없는 경우 또는 경우 GDI+ 픽셀 형식을 지원 하지 않는 파일의이 메서드에서 throw는 OutOfMemoryException 예외입니다.

파일 될 때까지 잠긴 상태로 유지는 Image 삭제 됩니다.

useEmbeddedColorManagement 매개 변수를 지정 하는지 여부를 새 Image 이미지 파일에 포함 된 색 관리 정보에 따라 색 보정을 적용 합니다.포함 된 정보는 International Color Consortium (ICC) 프로필, 감마 값 및 chromaticity 정보에 포함할 수 있습니다.

System_CAPS_note참고
Image 클래스 비트맵에 알파 투명도 지원 하지 않습니다. 알파 투명도 사용 하려면 PNG 이미지 픽셀당 32 비트를 사용 합니다.
예제
 
 

다음 코드 예제를 사용 하 여 새 비트맵을 구하는 방법의 FromFile 메서드. 에 대해서도 설명는 TextureBrush합니다.

이 예제는 Windows Forms에서 사용할 수 있습니다. 이라는 단추가 포함 된 폼을 만들 Button2합니다. 코드를 폼에 붙여넣고 연결의 Button2_Click 메서드는 단추의 Click 이벤트입니다.

 
private:    void Button2_Click( System::Object^ /*sender*/, System::EventArgs^ /*e*/ )    {       try       {          Bitmap^ image1 = dynamic_cast<Bitmap^>(Image::FromFile( "C:\\Documents and Settings\\"          "All Users\\Documents\\My Music\\music.bmp", true ));          TextureBrush^ texture = gcnew TextureBrush( image1 );          texture->WrapMode = System::Drawing::Drawing2D::WrapMode::Tile;          Graphics^ formGraphics = this->CreateGraphics();          formGraphics->FillEllipse( texture, RectangleF(90.0F,110.0F,100,100) );          delete formGraphics;       }       catch ( System::IO::FileNotFoundException^ )        {          MessageBox::Show( "There was an error opening the bitmap."          "Please check the path." );       }    }

 

 

 

 

=======================

=======================

=======================

 

 

 

 

출처: http://stackoverflow.com/questions/182988/how-to-draw-argb-bitmap-using-gdi

 

I have valid HBITMAP handle of ARGB type. How to draw it using GDI+?
I've tried method: graphics.DrawImage(Bitmap::FromHBITMAP(m_hBitmap, NULL), 0, 0); But it doesn't use alpha channel.
shareimprove this question
 

4 Answers

I've got working sample:
// 1. Get info using bitmap handle: image size, bits
BITMAP bmpInfo;
::GetObject(m_hBitmap, sizeof(BITMAP), &bmpInfo);
int cxBitmap = bmpInfo.bmWidth;
int cyBitmap = bmpInfo.bmHeight;
void* bits = bmpInfo.bmBits;

// 2. Create & draw new GDI+ bitmap using bits with pixel format PixelFormat32bppARGB
Gdiplus::Graphics graphics(dcMemory);
Gdiplus::Bitmap bitmap(cxBitmap, cyBitmap, cxBitmap*4, PixelFormat32bppARGB, (BYTE*)bits);
graphics.DrawImage(&bitmap, 0, 0);
shareimprove this answer
 
 
.NET offers the static Image.FromHbitmap method. You can then use this image and invoke DrawImage on the target Graphics object.
shareimprove this answer
 
    
This method doesn't draw transparent color. Here is the question. How to notify Gdi+ I want to draw exactly ARGB bitmap? – SeraTJ Oct 8 '08 at 14:18
1  
GDI+ Bitmap object has a constructor that takes Width, Height and PixelFormat as parameters. Once constructed, the bitmap will be in the desired bit depth and include an Alpha channel if requested. – Jeff BOct 8 '08 at 14:25
Ah... but .Net doesn't use HBITMAP and GDI+ is a C++ library atop the basic Windows GDI, so I'm assuming you're using non-.Net C++.
GDI+ has a Bitmap class, which has a FromHBITMAP() method.
Once you have the GDI+ Bitmap instance, you can use it with the GDI+ library.
Of course, if you can write your program in C# using .Net it will be a lot easier.
shareimprove this answer
 
I had similar issues getting my transparent channel to work. In my case, I knew what the background color should be used for the transparent area (it was solid). I used the Bitmap.GetHBITMAP(..) method and passed in the background color to be used for the transparent area. This was a much easier solution that other attempts I was trying using LockBits and re-creating the Bitmap with PixelFormat32bppARGB, as well as cloning. In my case, the Bitmap was ignoring the alpha channel since it was created from Bitmap.FromStream.
I also had some very strange problems with the background area of my image being changed slightly. For example, instead of pure white, it was off white like 0xfff7f7. This was the case whether I was using JPG (with blended colors) or with PNG and transparent colors.
See my question and solution at
GDI+ DrawImage of a JPG with white background is not white

 

 

 

 

 

 

=======================

=======================

=======================

 

 

 

 

 

출처: http://stackoverflow.com/questions/335273/how-to-create-a-gdiplusbitmap-from-an-hbitmap-retaining-the-alpha-channel-inf

 

 

When I create a new Gdiplus::Bitmap using the Bitmap::FromHBITMAP function, the resulting Bitmap is opaque - none of the partial transparency from the original HBITMAP is preserved.

Is there a way to create a Gdiplus::Bitmap from an HBITMAP which brings across the alpha channel data?

shareimprove this question
    
Do you know for sure that the HBITMAP has an alpha channel to start with? For instance, did you create it as a DIB with BI_RGB and 32bpp or some other way? – Johann Gerell Dec 3 '08 at 10:33
    
Yes, it does have transparency. It draws nicely using the ::AlphaBlend() function. – mackenir Dec 3 '08 at 13:44
    
(I created it in C# using new Bitmap(string filename) and the calling GetHBitmap() on the .NET bitmap object)– mackenir Dec 3 '08 at 13:46

 

 

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

 

 

 

I think working code is more useful than instructions, so:
#include <GdiPlus.h> #include <memory> Gdiplus::Status HBitmapToBitmap( HBITMAP source, Gdiplus::PixelFormat pixel_format, Gdiplus::Bitmap** result_out ) { BITMAP source_info = { 0 }; if( !::GetObject( source, sizeof( source_info ), &source_info ) ) return Gdiplus::GenericError; Gdiplus::Status s; std::auto_ptr< Gdiplus::Bitmap > target( new Gdiplus::Bitmap( source_info.bmWidth, source_info.bmHeight, pixel_format ) ); if( !target.get() ) return Gdiplus::OutOfMemory; if( ( s = target->GetLastStatus() ) != Gdiplus::Ok ) return s; Gdiplus::BitmapData target_info; Gdiplus::Rect rect( 0, 0, source_info.bmWidth, source_info.bmHeight ); s = target->LockBits( &rect, Gdiplus::ImageLockModeWrite, pixel_format, &target_info ); if( s != Gdiplus::Ok ) return s; if( target_info.Stride != source_info.bmWidthBytes ) return Gdiplus::InvalidParameter; // pixel_format is wrong! CopyMemory( target_info.Scan0, source_info.bmBits, source_info.bmWidthBytes * source_info.bmHeight ); s = target->UnlockBits( &target_info ); if( s != Gdiplus::Ok ) return s; *result_out = target.release(); return Gdiplus::Ok; }
shareimprove this answer
 
    
I had similar problem with a CBitmap, from which I retrieved the HBITMAP. In that case ::GetObject()left source_info.bmBits set to NULL. I could solve this by calling myCBitmapPtr->GetBitmapBits(source_info.bmWidthBytes * source_info.bmHeight, target_info.Scan0) – foraidt Aug 19 '14 at 13:32 
    
BTW, the return values are nicely checked in your example but if source_info.bmBits is NULL, there's an access violation in the call to CopyMemory(). – foraidt Aug 19 '14 at 13:35 

 

 

 

반응형

 

 

728x90

 

 

 

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

 

It turns out that GDI+ never brings across the alpha channel when creating a Bitmap from an HBITMAP.

The answer is to:

  • Use GetObject passing in a BITMAP and the HBITMAP, to get the width and height (and if the input bitmap is a DIB, the pixel data) of the input HBITMAP.
  • Create a Bitmap of the correct size with 32 bit PARGB pixel format.
  • Use LockBits to get hold of the pixelData memory of your new Bitmap.
  • If you got the pixels from GetObject, copy the ARGB values across using memcpy.
  • Call UnlockBits on the new Bitmap.

In my case, the format of the input HBITMAP is correct for doing a straight memcpy from input bitmap pixel data to the new Bitmap pixel data.

If you didnt get the input pixel data from GetObject, use GetDIBits to get a copy in the correct format.

 

 

 

 

=======================

=======================

=======================

 

 

 

 

 

출처: http://stackoverflow.com/questions/37901425/get-32-bit-rgba-image-from-windows-clipboard

 

I want my app (which works with RGBA8888 images) to be able to paste images from the Windows clipboard. So it should be able to read images off the clipboard that come from any common raster image apps like Gimp, Photoshop, MSPaint, etc.
From reading up on the clipboard functions, it seems I should be able to call GetClipboardData(CF_DIBV5) to get access to pretty much any bitmap type that's on the Clipboard since Windows automatically converts between that and CF_BITMAP and CF_DIB. But from reading up on the DIB format, I see that there is an immense number of possible combinations of bit depth, RGB order, optional compression, etc. It seems like what I'm doing would be a common task, but I don't see any conversion functions in the Windows API (unless I'm poor at searching), and this seems like something that would take a week to write to support all possible formats. So I'm wondering if I've overlooked something obvious. Or if there is some kind of assumption I can make to simplify this...like if all the popular image apps happen to copy images to the clipboard in uncompressed/unindexed formats.
UPDATE: Here's what I have so far:
HGLOBAL clipboard = GetClipboardData(CF_DIBV5); exists = clipboard != NULL; int dataLength = GlobalSize(clipboard); exists = dataLength != 0; if (exists) { LPTSTR lockedClipboard = GlobalLock(clipboard); exists = lockedClipboard != NULL; if (exists) { BITMAPV5HEADER *header = (BITMAPV5HEADER*)lockedClipboard; LONG width = header->bV5Width; LONG height = header->bV5Height; BYTE *bits = header + sizeof(header) + header->bV5ClrUsed * sizeof(RGBQUAD); //Now what? Need function to convert the bits to something uncompressed. GlobalUnlock(clipboard); } }
UPDATE 2:
To clarify, I need literally uncompressed 32 bit image data (RRGGBBAA) which I can manipulate however I like in a cross-platform app. I have no need to use Windows APIs to draw this image to screen.
I am aware of a 3rd party library called stdb_image.h that can load .bmps, .jpgs, and .pngs into the type of data I need. So if there's a way I can turn the clipboard data into bitmap or png file data without losing alpha, then I'll be in good shape.
shareimprove this question
GetDIBits and SetDIBits transform bitmap data between DIBs and DDBs, converting according to the parameters from BITMAPINFO. – GSerg Jun 18 '16 at 20:49
    
GetClipboardData(CF_BITMAP) should be enough, unless you want alpha-transparency levels. Show what you have done so far and what problem you have with specific programs (Microsoft paint.exe shouldn't be a problem) – Barmak Shemirani Jun 19 '16 at 5:18
    
I'm working through understanding the getDIBits function and will update if I can't get it working. I do need alpha. Looks like for non-indexed bitmaps, alpha is in the fourth byte (each pixel must use a long even if only RGB) but there's nothing in the header to determine if there's alpha. – Tenfour04 Jun 19 '16 at 16:27
    
@BarmakShemirani @GSerg I updated with my code so far. Unsure if I added correctly to get the bits pointer. This is unusable with GetDIBits or SetDIBits because I have a DIB, not a DDB HBITMAP. I need CF_DIBV5 because I need alpha if it's on the clipboard. – Tenfour04 Jun 21 '16 at 2:54

2 Answers

The basic strategy I've found is to check if there's a raw PNG on the clipboard and use that first if available. That's the easiest. Some apps, such as GIMP, copy images as PNG to the clipboard.
Then check for CF_DIBV5. The location of the actual bits depends on whether the "compression" is BI_BITFIELDS:
int offset = bitmapV5Header->bV5Size + bitmapV5Header->bV5ClrUsed * (bitmapV5Header->bV5BitCount > 24 ? sizeof(RGBQUAD) : sizeof(RGBTRIPLE)); if (compression == BI_BITFIELDS) offset += 12; //bit masks follow the header BYTE *bits = (BYTE*)bitmapV5Header + offset;
If the header says compression is BI_BITFIELDS, then the data is already as I needed it.
If the header says compression is BI_RGB and the bit count is 24 or 32, then I can unpack the bytes. 24 bytes means row size might not land on a DWORD boundary, so you have to watch for that.
Finally, lower bit counts than 24 likely mean indexed color, which I don't have working yet.
shareimprove this answer
 
 
Here is example of usage for CF_DIBV5 and CF_DIB. It's best to use CF_DIB as backup option. Note, this code won't work for palette based images (if it is not guaranteed 32bit then see the method further down)
You can use SetDIBitsToDevice to draw directly on HDC, or use SetDIBits
GDI functions don't support alpha transparency (except for a couple of functions like TransparentBlt), in general you have to use libraries such as GDI+ for that.
void foo(HDC hdc) { if (!OpenClipboard(NULL)) return; HANDLE handle = GetClipboardData(CF_DIBV5); if (handle) { BITMAPV5HEADER* header = (BITMAPV5HEADER*)GlobalLock(handle); if (header) { BITMAPINFO bmpinfo; memcpy(&bmpinfo.bmiHeader, header, sizeof(BITMAPINFOHEADER)); bmpinfo.bmiHeader.biSize = sizeof(BITMAPINFO); //(use `header` to access other BITMAPV5HEADER information) int w = bmpinfo.bmiHeader.biWidth; int h = bmpinfo.bmiHeader.biHeight; const char* bits = (char*)(header) + header->bV5Size; //draw using SetDIBitsToDevice SetDIBitsToDevice(hdc,0,0,w,h,0,0,0,h,bits,&bmpinfo,DIB_RGB_COLORS); } } else { handle = GetClipboardData(CF_DIB); if (handle) { BITMAPINFO* bmpinfo = (BITMAPINFO*)GlobalLock(handle); if (bmpinfo) { int w = bmpinfo->bmiHeader.biWidth; int h = bmpinfo->bmiHeader.biHeight; const char* bits = (char*)(bmpinfo)+bmpinfo->bmiHeader.biSize; SetDIBitsToDevice(hdc, 0, 0, w, h, 0, 0, 0, h, bits, bmpinfo, 0); } } } CloseClipboard(); }
If the original image is palette based, you would have to convert to 32bit. Alternatively you could add BITMAPFILEHEADER to the data (assuming the source is bitmap) then pass to the other library.
This is an example using CreateDIBitmap and GetDIBits to make sure the pixels are in 32bit:
HANDLE handle = GetClipboardData(CF_DIB); if (handle) { BITMAPINFO* bmpinfo = (BITMAPINFO*)GlobalLock(handle); if (bmpinfo) { int offset = (bmpinfo->bmiHeader.biBitCount > 8) ? 0 : sizeof(RGBQUAD) * (1 << bmpinfo->bmiHeader.biBitCount); const char* bits = (const char*)(bmpinfo)+bmpinfo->bmiHeader.biSize + offset; HBITMAP hbitmap = CreateDIBitmap(hdc, &bmpinfo->bmiHeader, CBM_INIT, bits, bmpinfo, DIB_RGB_COLORS); //convert to 32 bits format (if it's not already 32bit) BITMAP bm; GetObject(hbitmap, sizeof(bm), &bm); int w = bm.bmWidth; int h = bm.bmHeight; char *bits32 = new char[w*h*4]; BITMAPINFOHEADER bmpInfoHeader = { sizeof(BITMAPINFOHEADER), w, h, 1, 32 }; HDC hdc = GetDC(0); GetDIBits(hdc, hbitmap, 0, h, bits32, (BITMAPINFO*)&bmpInfoHeader, DIB_RGB_COLORS); ReleaseDC(0, hdc); //use bits32 for whatever purpose... //cleanup delete[]bits32; } }
shareimprove this answer
 
    
In your last function, I'm not following what's going on. Is CreateDIBSection the only way to get a Bitmap from the clipboard? And what does SetDIBits actually do? What I need is simply an array of bytes of uncompressed 32bit image data. I am using it to load the image into OpenGL. Actually, if I could just convert the clipboard content directly into a .bmp, .png, or .jpg byte array (same bytes that could be saved as a file), I could easily pass it into the stdb_image.h 3rd party library to get the image data in whatever format I want.– Tenfour04 Jun 22 '16 at 2:39 
    
The BITMAPV5HEADER mentions JPG or PNG compression. I don't know if that means the following bits are literally the file data for one of those image types, or simply that that style of compression is being used. – Tenfour04 Jun 22 '16 at 2:46
    
If header->bV5BitCount is 32, then bits points to the "32bit image data" that you want. If it is 24, then it must be converted to 32bit. – Barmak Shemirani Jun 22 '16 at 3:14
    
So is CreateDIBSection the way that you convert it? And what if it's 32 bit compressed data? – Tenfour04Jun 22 '16 at 3:15
    
I don't know, your question is getting too complicated. Note that if the source is jpeg file, the third party program may choose to make it available to other program as CF_DIB, usually 32bit but sometimes as 24bit or as palette image. – Barmak Shemirani Jun 22 '16 at 3:34

 

 

 

=======================

=======================

=======================

 

 

 

 

 

출처: https://support.microsoft.com/ko-kr/help/309482/image-file-is-locked-when-you-set-the-picturebox-image-property-to-a-file

 

PRB: PictureBox Image 속성을 파일로 설정하면 이미지 파일이 잠긴다

 

현상

그림 파일이 포함되어 있는 PictureBox 컨트롤을 로드하면 Microsoft Visual Studio .NET 통합 개발 환경(IDE)에서 해당 파일을 계속 잠급니다. 디자인 타임에 수동으로 PictureBox 컨트롤의 Image 속성을 파일로 설정하거나 런타임에 FromFile 메서드를 사용하면 이러한 문제가 발생합니다.

해결 방법

이 문제를 해결하려면 FileStream 개체를 다음과 같이 사용하십시오.
Dim fs As System.IO.FileStream
' Specify a valid picture file path on your computer.
fs = New System.IO.FileStream("C:\WINNT\Web\Wallpaper\Fly Away.jpg", 
     IO.FileMode.Open, IO.FileAccess.Read)
PictureBox1.Image = System.Drawing.Image.FromStream(fs)
fs.Close()

현재 상태

이것은 의도적으로 설계된 동작입니다.

추가 정보

디자인 타임

디자인 타임에 PictureBox 컨트롤의 Image 속성을 설정하면 Visual Studio .NET IDE가 그림 파일을 잠급니다. Image 속성을 재설정하거나 PictureBox 컨트롤을 삭제해도 그림 파일은 잠긴 상태로 있습니다. 그림 파일을 잠금 해제하는 유일한 방법은 Visual Studio .NET IDE를 닫는 것입니다.

문제를 재현하는 방법

  1. Visual Studio .NET에서 새 Visual Basic Windows 응용 프로그램 프로젝트를 만듭니다. 기본적으로 Form1이 만들어집니다.
  2. Form1에 PictureBox 컨트롤을 추가하고 Image 속성을 그림 파일로 설정합니다.
  3. Windows 탐색기에서, PictureBox 컨트롤에서 Image 속성으로 사용한 그림 파일의 이름을 바꾸어 봅니다. 공유 위반 오류 메시지가 나타납니다.
  4. 속성 창에서 Image 속성을 마우스 오른쪽 단추로 누른 다음 다시 설정을 누릅니다. 그림 파일의 이름을 바꾸어 봅니다. 공유 위반 오류 메시지가 나타납니다.
  5. Form1에서 PictureBox 컨트롤을 삭제한 다음 Windows 탐색기에서 그림 파일의 이름을 바꾸어 봅니다. 공유 위반 오류 메시지가 나타납니다.

런타임

Image.FromFile 메서드를 사용하여 PictureBox 컨트롤의 그림을 로드하면 응용 프로그램을 시작할 때 그림 파일이 잠깁니다. 응용 프로그램이 실행되는 동안에도 그림 파일이 잠긴 상태로 있습니다. 런타임에 Image 속성을 Nothing으로 설정해도 그림 파일이 잠깁니다.

문제를 재현하는 방법

  1. Visual Studio .NET에서 새 Visual Basic Windows 응용 프로그램 프로젝트를 만듭니다. 기본적으로 Form1이 만들어집니다.
  2. PictureBox 컨트롤 하나와 Button 컨트롤 하나를 Form1에 추가합니다.
  3. Button 컨트롤에 대한 Click 이벤트에서 다음 코드를 붙여넣습니다.
    ' Specify a valid picture file path on your machine below
    PictureBox1.Image = Image.FromFile("C:\WINNT\Web\Wallpaper\Fly Away.jpg")
  4. F5 키를 눌러 응용 프로그램을 실행한 다음 Button 컨트롤을 눌러 PictureBox 컨트롤의 그림을 로드합니다.
  5. 응용 프로그램이 실행되는 동안 Windows 탐색기를 사용하여 그림 파일의 이름을 바꾸어 봅니다. 공유 위반 오류 메시지가 나타나고 파일의 이름을 바꿀 수가 없습니다.

 

 

 

 

=======================

=======================

=======================

 

 

 

 

 

 

 

 

반응형