Loading Pixbuf to Image Widget in GTK# - c#

I'm trying to load an image file from harddisk to the image widget in GTK#.I know that Pixbuf is used to represent the image.In .net i had used Bitmap b=Bitmap.from File ("c:\windows\file.jpg")
and assigned PictureBox=b;
How can i do this with Image Widget
Update:
I tried
protected void OnButton2ButtonPressEvent (object o, ButtonPressEventArgs args)
{
var buffer = System.IO.File.ReadAllBytes ("i:\\Penguins.jpg");
var pixbuf = new Gdk.Pixbuf (buffer);
image103.Pixbuf = pixbuf;
}
But it does not work.

Try this:
var buffer = System.IO.File.ReadAllBytes ("path\\to\\file");
var pixbuf = new Gdk.Pixbuf (buffer);
image.Pixbuf = pixbuf;
Also you may create a pixbuf like this:
var pixbuf = new Gdk.Pixbuf ("path\\to\\file");
But when I tried to use this constructor with path containing some russian symbols I had an exception because of wrong encoding.
Update
I don't know any legacy method to set in gtk# image stretch option and I usually solve this problem with creation of new control. So right click on the project->Add->Create Widget and set the name to ImageControl. Add Image on created widget. Then edit ImageControl's code like this:
[System.ComponentModel.ToolboxItem (true)]
public partial class ImageControl : Gtk.Bin
{
private Pixbuf original;
private bool resized;
public Gdk.Pixbuf Pixbuf {
get
{
return image.Pixbuf;
}
set
{
original = value;
image.Pixbuf = value;
}
}
public ImageControl ()
{
this.Build ();
}
protected override void OnSizeAllocated (Gdk.Rectangle allocation)
{
if ((image.Pixbuf != null) && (!resized)) {
var srcWidth = original.Width;
var srcHeight = original.Height;
int resultWidth, resultHeight;
ScaleRatio (srcWidth, srcHeight, allocation.Width, allocation.Height, out resultWidth, out resultHeight);
image.Pixbuf = original.ScaleSimple (resultWidth, resultHeight, InterpType.Bilinear);
resized = true;
} else {
resized = false;
base.OnSizeAllocated (allocation);
}
}
private static void ScaleRatio(int srcWidth, int srcHeight, int destWidth, int destHeight, out int resultWidth, out int resultHeight)
{
var widthRatio = (float)destWidth / srcWidth;
var heigthRatio = (float)destHeight / srcHeight;
var ratio = Math.Min(widthRatio, heigthRatio);
resultHeight = (int)(srcHeight * ratio);
resultWidth = (int)(srcWidth * ratio);
}
}
Now you may set pictures with Pixbuf property of ImageControl's widget.

Related

Problem with loading image from bytes array

I encountered strange behaviour when loading image from byte array aquired from stream. Most images are correct, I would say 99% of them. But i saw so far two times something like this below. Image in the middle is shown like a set of random pixels, not the real image.
Image can be loaded correctly in other client application (sliverlight) but i can't show that.
In WPF client i have something like that:
Does someone had issue like this? Or any idea what might cause it? Maybe i should look on server side (image is show in other, older client and code to load that is known to me).
Code looks like that:
public async Task<ImageCreatePictureBox> CreatePictureBox(IBaseObj pmIBaseObj, IObj pmObj)
{
var lcContainer = new Grid
{
Width = pmObj.PresObj.Width,
Height = pmObj.PresObj.Height
};
var gridBorder = new Border();
CustomImg imageControl = null;
FrameworkElement lcFrameworkElement = lcContainer;
if (!(pmIBaseObj is ImageBaseObj lcImageBaseObj))
return new ImageCreatePictureBox(null, lcContainer, lcFrameworkElement, pmObj);
if (!lcImageBaseObj.CustomBitMap)
{
try
{
var bitmapImage = BitmapImageHelper.ByteArrayToBitmapSource(lcImageBaseObj.Image, lcImageBaseObj.ImageWidth, lcImageBaseObj.ImageHeight);
imageControl = new CustomImg(pmIBaseObj.Width, pmIBaseObj.Height, pmObj)
{
Source = bitmapImage,
Height = lcImageBaseObj.Height,
Width = lcImageBaseObj.Width
};
}
catch (Exception e)
{
var src = new BitmapImage(new Uri(Helper.GetPathToImage("dummy")));
imageControl = new CustomImg(pmIBaseObj.Width, pmIBaseObj.Height, pmObj)
{
Source = src,
Height = lcImageBaseObj.Height,
Width = lcImageBaseObj.Width
};
Helper.WriteToDebug(e);
}
}
else
{
try
{
var bitmapImage = BitmapImageHelper.ByteArrayToBitmapSource(lcImageBaseObj.Image, lcImageBaseObj.ImageWidth, lcImageBaseObj.ImageHeight);
imageControl = new CustomImg(pmIBaseObj.Width, pmIBaseObj.Height, pmObj)
{
Source = bitmapImage,
Height = lcImageBaseObj.Height,
Width = lcImageBaseObj.Width
};
}
catch (Exception e)
{
if (imageControl == null)
imageControl = new CustomImg(pmIBaseObj.Width, pmIBaseObj.Height, pmObj);
var src = new BitmapImage(new Uri(Helper.GetPathToImage("dummy")));
imageControl = new CustomImg(pmIBaseObj.Width, pmIBaseObj.Height, pmObj)
{
Source = src,
Height = lcImageBaseObj.Height,
Width = lcImageBaseObj.Width
};
Helper.WriteToDebug(e);
}
}
(...)
return new ImageCreatePictureBox(imageControl, lcContainer, lcFrameworkElement, pmObj);
}
public static BitmapSource ByteArrayToBitmapSource(Byte[] BArray, int imgWidth, int imgHeight)
{
try
{
var width = imgWidth;
var height = imgHeight;
var dpiX = 90d;
var dpiY = 90d;
var pixelFormat = PixelFormats.Pbgra32;
var bytesPerPixel = (pixelFormat.BitsPerPixel + 7) / 8;
var stride = bytesPerPixel * width;
var bitmap = BitmapSource.Create(width, height, dpiX, dpiY, pixelFormat, null, BArray, stride);
return bitmap;
}
catch (Exception e)
{
return BytesToBitmapImage(BArray);
}
}

Exporting UltraExpandableGroupBox default expansion indicator

I am using a UltraExpandableGroupBox in my WinForms application. And I am using the Office2003 style with it. However, I would like to reverse the Expanded and Collapsed Indicator images used. I tried to export the images from the .isl file, but these images don't seems to be among the images exported. How do I access these images?
When the ViewStyle property for the UltraExpandableGroupBox control is set to the GroupBoxViewStyle.Office2003 the Expanded/Collapsed indicator uses an embedded bitmap.
Code below demonstrates how this bitmap can be obtained from the assembly on the runtime and can be used to reverse the current Expanded/Collapsed indicators:
private void ReverseImage_Click(object sender, EventArgs e)
{
var imageName = "GroupBox.ExpansionIndicator_Chevron.bmp";
System.IO.Stream stream = typeof(UltraExpandableGroupBox).Module.Assembly.GetManifestResourceStream(typeof(UltraExpandableGroupBox), imageName);
if (stream != null)
{
// The source bitmap has 7x10px size.
var image = Bitmap.FromStream(stream);
// Converting the image to 16x16 pixels
ultraExpandableGroupBox1.ExpansionIndicatorExpanded = ResizeImage(image, 16, 16);
// Rotation
using (var bmp = new Bitmap(image))
{
bmp.RotateFlip(RotateFlipType.Rotate180FlipNone);
image = bmp.Clone() as Image;
// Exporting bitmap to a file
bmp.Save(#".\" + imageName, ImageFormat.Bmp);
}
ultraExpandableGroupBox1.ExpansionIndicatorCollapsed = ResizeImage(image, 16, 16);
}
}
public static Image ResizeImage(Image image, int new_height, int new_width)
{
var dest = new Bitmap(new_width, new_height);
var g = Graphics.FromImage(dest);
g.InterpolationMode = InterpolationMode.High;
g.DrawImage(image, (dest.Width - image.Width)/2, (dest.Height-image.Height)/2);
return dest;
}
Exported to a file the Expanded/Collapsed indicator bitmap looks like on the picture below:
You can achieve this with simple DrawFilter. Set to your UltraExpandableGroupBox DraFilter property like this:
this.myUltraExpandableGroupBox.DrawFilter = new MyDrawFilter(expandedIndicator, collapsedInidcator);
Then create a new class named MyDrawFilter and let it inherit IUIElementDrawFilter. Your draw filter class may look like this:
public class MyDrawFilter : IUIElementDrawFilter
{
Image expandedIndicator;
Image collapsedIndicator;
public MyDrawFilter(Image expandedIndicator, Image collapsedInidcator)
{
this.expandedIndicator = expandedIndicator;
this.collapsedIndicator = collapsedInidcator;
}
public bool DrawElement(DrawPhase drawPhase, ref UIElementDrawParams drawParams)
{
if (drawParams.Element is GroupBoxExpansionIndicatorUIElement)
{
// if groupbox is expanded change the image with one provided in the constructor
// as expandedIndicator
if ((drawParams.Element.Control as UltraExpandableGroupBox).Expanded)
{
(drawParams.Element.ChildElements[0] as ImageUIElement).Image = this.expandedIndicator;
}
// else gropbox is collapsed change the image with one provided in the constructor
// as collapsedIndicator
else
{
(drawParams.Element.ChildElements[0] as ImageUIElement).Image = this.collapsedIndicator;
}
}
return false;
}
public DrawPhase GetPhasesToFilter(ref UIElementDrawParams drawParams)
{
// filter when GroupBoxExpansionIndicatorUIElement should be drawn. This element has
// one child UIElement of ImageUIElement type. This UIElement holds the expansion
// indicator image.
if (drawParams.Element is GroupBoxExpansionIndicatorUIElement)
{
// we return BeforeDrawChildeElements in order to be able to change the image
return DrawPhase.BeforeDrawChildElements;
}
return DrawPhase.None;
}
}

Printing a local file on Android via Xamarin.Forms

I need to use the print dialog via Forms. I have found an solution on iOS but the android implementation is giving me problems.
As far as i can see it is not possible to call the Android print manager and parse a file to it.
It can only be a Android.Views.View, is that true?
To do that would be my ideal solution.
I have tried to convert my content (A webview showing a local pdf) to this android view but this seems also not really to work but i am out off my depths here.
in the code below i try to convert a forms.webview to an android.view and then parse it to the print manager.
This produce the print dialog but with a black white page.
var size = new Rectangle(webview.X, webview.Y, webview.Width, webview.Height);
var vRenderer = Xamarin.Forms.Platform.Android.Platform.CreateRenderer(webview);
var viewGroup = vRenderer.ViewGroup;
vRenderer.Tracker.UpdateLayout();
var layoutParams = new Android.Views.ViewGroup.LayoutParams((int)size.Width, (int)size.Height);
viewGroup.LayoutParameters = layoutParams;
webview.Layout(size);
viewGroup.Layout(0, 0, (int)webview.WidthRequest, (int)webview.HeightRequest);
var printMgr = (Android.Print.PrintManager)Forms.Context.GetSystemService(Android.Content.Context.PrintService);
var docAdt = new Droid.GenericPrintAdapter(Forms.Context, viewGroup);
printMgr.Print("test", docAdt, null);
The next is the "GenericPrintAdapter"
public class GenericPrintAdapter : PrintDocumentAdapter
{
View view;
Context context;
PrintedPdfDocument document;
float scale;
public GenericPrintAdapter(Context context, View view)
{
this.view = view;
this.context = context;
}
public override void OnLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle extras)
{
document = new PrintedPdfDocument(context, newAttributes);
CalculateScale(newAttributes);
var printInfo = new PrintDocumentInfo
.Builder("MyPrint.pdf")
.SetContentType(PrintContentType.Document)
.SetPageCount(1)
.Build();
callback.OnLayoutFinished(printInfo, true);
}
void CalculateScale(PrintAttributes newAttributes)
{
int dpi = Math.Max(newAttributes.GetResolution().HorizontalDpi, newAttributes.GetResolution().VerticalDpi);
int leftMargin = (int)(dpi * (float)newAttributes.MinMargins.LeftMils / 1000);
int rightMargin = (int)(dpi * (float)newAttributes.MinMargins.RightMils / 1000);
int topMargin = (int)(dpi * (float)newAttributes.MinMargins.TopMils / 1000);
int bottomMargin = (int)(dpi * (float)newAttributes.MinMargins.BottomMils / 1000);
int w = (int)(dpi * (float)newAttributes.GetMediaSize().WidthMils / 1000) - leftMargin - rightMargin;
int h = (int)(dpi * (float)newAttributes.GetMediaSize().HeightMils / 1000) - topMargin - bottomMargin;
scale = Math.Min((float)document.PageContentRect.Width() / w, (float)document.PageContentRect.Height() / h);
}
public override void OnWrite(PageRange[] pages, ParcelFileDescriptor destination,
CancellationSignal cancellationSignal, WriteResultCallback callback)
{
PrintedPdfDocument.Page page = document.StartPage(0);
page.Canvas.Scale(scale, scale);
view.Draw(page.Canvas);
document.FinishPage(page);
WritePrintedPdfDoc(destination);
document.Close();
document.Dispose();
callback.OnWriteFinished(pages);
}
void WritePrintedPdfDoc(ParcelFileDescriptor destination)
{
var javaStream = new Java.IO.FileOutputStream(destination.FileDescriptor);
var osi = new OutputStreamInvoker(javaStream);
using (var mem = new MemoryStream())
{
document.WriteTo(mem);
var bytes = mem.ToArray();
osi.Write(bytes, 0, bytes.Length);
}
}
}
I have now a "working" solution.
This gets the current Android.Webkir.WebView and create the printAdapter from that.
Thanks to #SushiHangover for pointing me in the right direction.
Its a bit of a hack but works for my needs.
If anyone else ever needs this i have included both the Android and iOS code.
#if __ANDROID__
var vRenderer = Xamarin.Forms.Platform.Android.Platform.GetRenderer(webview);
var viewGroup = vRenderer.ViewGroup;
for (int i = 0; i < viewGroup.ChildCount; i++)
{
if (viewGroup.GetChildAt(i).GetType().Name == "WebView")
{
var AndroidWebView = viewGroup.GetChildAt(i) as Android.Webkit.WebView;
var tmp = AndroidWebView.CreatePrintDocumentAdapter("print");
var printMgr = (Android.Print.PrintManager)Forms.Context.GetSystemService(Android.Content.Context.PrintService);
printMgr.Print("print", tmp, null);
break;
}
}
#elif __IOS__
var printInfo = UIKit.UIPrintInfo.PrintInfo;
printInfo.Duplex = UIKit.UIPrintInfoDuplex.LongEdge;
printInfo.OutputType = UIKit.UIPrintInfoOutputType.General;
printInfo.JobName = "AppPrint";
var printer = UIKit.UIPrintInteractionController.SharedPrintController;
printer.PrintInfo = printInfo;
printer.PrintingItem = Foundation.NSData.FromFile(pdfPath);
printer.ShowsPageRange = true;
printer.Present(true, (handler, completed, err) =>
{
if (!completed && err != null)
{
System.Diagnostics.Debug.WriteLine("Printer Error");
}
});
#endif

Change width and heigth of saving view

I have code for saving Layout as bitmap
Here it is
public static class App
{
public static Java.IO.File _file;
public static Java.IO.File _dir;
public static Bitmap bitmap;
}
[Activity(Label = "SaveViewAsBitMap", ScreenOrientation = ScreenOrientation.Landscape, Theme = "#android:style/Theme.Black.NoTitleBar")]
public class Badge : Activity
{
public static string name_from_activity;
public static string surname_from_activity;
public string inn_from_activity;
private ImageView _imageView;
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
// Make it available in the gallery
Intent mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile);
Uri contentUri = Uri.FromFile(App._file);
mediaScanIntent.SetData(contentUri);
SendBroadcast(mediaScanIntent);
// Display in ImageView. We will resize the bitmap to fit the display
// Loading the full sized image will consume to much memory
// and cause the application to crash.
int height = Resources.DisplayMetrics.HeightPixels;
int width = _imageView.Height;
App.bitmap = App._file.Path.LoadAndResizeBitmap(width, height);
if (App.bitmap != null)
{
_imageView.SetImageBitmap(App.bitmap);
App.bitmap = null;
}
// Dispose of the Java side bitmap.
GC.Collect();
}
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
TextView bt1 = FindViewById<TextView>(Resource.Id.Surname);
bt1.Click += Bt1_Click;
name_from_activity = Intent.GetStringExtra("Name");
surname_from_activity = Intent.GetStringExtra("Surname");
inn_from_activity = Intent.GetStringExtra("INN");
TextView Name = FindViewById<TextView>(Resource.Id.Name);
Name.Text = name_from_activity;
TextView Surname = FindViewById<TextView>(Resource.Id.Surname);
Surname.Text = surname_from_activity;
string path = "Fonts/proximanovaregular.otf";
Typeface tf = Typeface.CreateFromAsset(Assets, path); //Custom fonts for TextBoxes
Name.Typeface = tf;
Surname.Typeface = tf;
var barcodeWriter = new ZXing.Mobile.BarcodeWriter //Creating qr code using Intent data
{
Format = ZXing.BarcodeFormat.QR_CODE,
Options = new ZXing.Common.EncodingOptions //Options for QR code dimensions
{
Width = 600,
Height = 600
}
};
ImageView qr = FindViewById<ImageView>(Resource.Id.qr);
var bitmap = barcodeWriter.Write(inn_from_activity);
qr.SetImageBitmap(bitmap);
if (IsThereAnAppToTakePictures())
{
CreateDirectoryForPictures();
_imageView = FindViewById<ImageView>(Resource.Id.photo);
TakeAPicture();
}
}
//Button handler for bitmap
private void Bt1_Click(object sender, System.EventArgs e)
{
View v = FindViewById<LinearLayout>(Resource.Id.badge2);
Bitmap myBitMap = createViewBitmap(v);
Drawable drawable = new BitmapDrawable(myBitMap);
//img.SetBackgroundDrawable(drawable);
// MediaStore.Images.Media.InsertImage(ContentResolver, myBitMap, "title", "description");
saveImage(myBitMap);
Intent mediaScanIntent2 = new Intent(Intent.ActionMediaScannerScanFile);
Java.IO.File myFile = new Java.IO.File(Android.OS.Environment.ExternalStorageDirectory + "/DCIM/Camera", name_from_activity.ToString() + surname_from_activity.ToString() + ".jpg");
Android.Net.Uri contentUri = Android.Net.Uri.FromFile(myFile);
mediaScanIntent2.SetData(contentUri);
SendBroadcast(mediaScanIntent2);
}
//Creating bitmap from view via Canvas
public Bitmap createViewBitmap(View v)
{
Bitmap bitmap = Bitmap.CreateBitmap(v.Width, v.Height,
Bitmap.Config.Argb8888);
Canvas canvas = new Canvas(bitmap);
v.Draw(canvas);
return bitmap;
}
//Check if directory exists, if no, create it
private void CreateDirectoryForPictures()
{
App._dir = new Java.IO.File(
Environment.GetExternalStoragePublicDirectory(
Environment.DirectoryPictures), "CameraAppDemo");
if (!App._dir.Exists())
{
App._dir.Mkdirs();
}
}
//Returning avialable activities
private bool IsThereAnAppToTakePictures()
{
Intent intent = new Intent(MediaStore.ActionImageCapture);
IList<ResolveInfo> availableActivities =
PackageManager.QueryIntentActivities(intent, PackageInfoFlags.MatchDefaultOnly);
return availableActivities != null && availableActivities.Count > 0;
}
//Method for opening default Camera Activity and making photo
private void TakeAPicture()
{
Intent intent = new Intent(MediaStore.ActionImageCapture);
App._file = new Java.IO.File(App._dir, String.Format("myPhoto_{0}.jpg", Guid.NewGuid()));
intent.PutExtra(MediaStore.ExtraOutput, Uri.FromFile(App._file));
StartActivityForResult(intent, 0);
}
//Method for saving image to device
public static void saveImage(Bitmap bmp)
{
try
{
using (var os = new System.IO.FileStream(Android.OS.Environment.ExternalStorageDirectory + "/DCIM/Camera/" + name_from_activity.ToString()+surname_from_activity.ToString() + ".jpg", System.IO.FileMode.CreateNew))
{
bmp.Compress(Bitmap.CompressFormat.Jpeg, 95, os);
}
}
catch (Exception e)
{
}
}
}
}
I need to save picture in 370*204 resolution
I try it like this
public Bitmap createViewBitmap(View v)
{
Bitmap bitmap = Bitmap.CreateBitmap(370, 204,
Bitmap.Config.Argb8888);
Canvas canvas = new Canvas(bitmap);
v.Draw(canvas);
return bitmap;
}
But it not works, it saves only part of layout.
How I need to write code?
Thank's for help.
I had build a prototype for one other project that I'm using...
Try this repository
This code Bitmap.CreateBitmap(370, 204,Bitmap.Config.Argb8888); will cut the source bitmap with width 370 and height 204. The bitmap not be scaled. Because you are still use the view to draw a bitmap.
When you get the view bitmap you need to zoom the bitmap:
public static Bitmap zoomImg(Bitmap bm, int newWidth, int newHeight)
{
int width = bm.Width;
int height = bm.Height;
float scaleWidth = ((float)newWidth) / width;
float scaleHeight = ((float)newHeight) / height;
Matrix matrix = new Matrix();
matrix.PostScale(scaleWidth, scaleHeight);
Bitmap newbm = Bitmap.CreateBitmap(bm, 0, 0, width, height, matrix, true);
return newbm;
}
public Bitmap createViewBitmap2(View v)
{
Bitmap bitmap = Bitmap.CreateBitmap(v.Width, v.Height,Bitmap.Config.Argb8888);
Canvas canvas = new Canvas(bitmap);
v.Draw(canvas);
return zoomImg(bitmap, 370, 204);
}

What is the best way to create custom item scrollable list view in c# .NET?

I want to create GUI application using .NET and I need to implement such kind of scrollable list with custom items. All items should grouped to 3 different groups and to include images, text and favourite star button as shown here:
I would also like to implement filtering using search box, but once I would be able to create such list with customizable items then I hope it would be much easier.
I tried using .NET list view, but I want each cell to look like 1 cell - with out any borders between the image, text, image.
I would extremely appreciate any thoughts about this manner!
The best way would be making control template for either WPF ListView or ListBox control.
For example, ListBox.ItemTemplate allows for custom item look.
If you would like to use 3rd party components, Better ListView allows this using owner drawing (requires subclassing BetterListView):
Here is a setup code for the control:
this.customListView = new CustomListView
{
Dock = DockStyle.Fill,
Parent = this
};
this.customListView.BeginUpdate();
for (int i = 0; i < 6; i++)
{
var item = new BetterListViewItem
{
Image = imageGraph,
Text = String.Format("Item no. {0}", i)
};
this.customListView.Items.Add(item);
}
var group1 = new BetterListViewGroup("First group");
var group2 = new BetterListViewGroup("Second group");
var group3 = new BetterListViewGroup("Third group");
this.customListView.Groups.AddRange(new[] { group1, group2, group3 });
this.customListView.Items[0].Group = group1;
this.customListView.Items[1].Group = group1;
this.customListView.Items[2].Group = group2;
this.customListView.Items[3].Group = group2;
this.customListView.Items[4].Group = group2;
this.customListView.Items[5].Group = group3;
this.customListView.AutoSizeItemsInDetailsView = true;
this.customListView.GroupHeaderBehavior = BetterListViewGroupHeaderBehavior.None;
this.customListView.ShowGroups = true;
this.customListView.LayoutItemsCurrent.ElementOuterPadding = new Size(0, 8);
this.customListView.EndUpdate();
and CustomListView class (implements custom drawing and interaction with star icons):
using BetterListView;
internal sealed class CustomListView : BetterListView
{
private const int IndexUndefined = -1;
private Image imageStarNormal;
private Image imageStarHighlight;
private int lastStarIndex = IndexUndefined;
private int currentStarIndex = IndexUndefined;
public CustomListView()
{
this.imageStarNormal = Image.FromFile("icon-star-normal.png");
this.imageStarHighlight = Image.FromFile("icon-star-highlight.png");
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
var item = HitTest(e.Location).ItemDisplay;
if (item == null)
{
return;
}
var bounds = GetItemBounds(item);
if (bounds == null)
{
return;
}
Rectangle boundsStar = GetStarBounds(bounds);
UpdateStarIndex(boundsStar.Contains(e.Location)
? item.Index
: IndexUndefined);
}
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
UpdateStarIndex(IndexUndefined);
}
protected override void OnDrawGroup(BetterListViewDrawGroupEventArgs eventArgs)
{
eventArgs.DrawSeparator = false;
base.OnDrawGroup(eventArgs);
}
protected override void OnDrawItem(BetterListViewDrawItemEventArgs eventArgs)
{
base.OnDrawItem(eventArgs);
Graphics g = eventArgs.Graphics;
BetterListViewItemBounds bounds = eventArgs.ItemBounds;
int imageWidth = this.imageStarNormal.Width;
int imageHeight = this.imageStarNormal.Height;
g.DrawImage(
(this.currentStarIndex == eventArgs.Item.Index) ? this.imageStarHighlight : this.imageStarNormal,
GetStarBounds(bounds),
0, 0, imageWidth, imageHeight,
GraphicsUnit.Pixel);
Rectangle boundsSelection = bounds.BoundsSelection;
g.DrawRectangle(
Pens.Gray,
new Rectangle(boundsSelection.Left, boundsSelection.Top, boundsSelection.Width - 1, boundsSelection.Height - 1));
}
private void UpdateStarIndex(int starIndex)
{
if (starIndex == this.lastStarIndex)
{
return;
}
bool isUpdated = false;
if (this.lastStarIndex != IndexUndefined)
{
Items[this.lastStarIndex].Invalidate();
isUpdated = true;
}
if (starIndex != IndexUndefined)
{
Items[starIndex].Invalidate();
isUpdated = true;
}
this.lastStarIndex = this.currentStarIndex;
this.currentStarIndex = starIndex;
if (isUpdated)
{
RedrawItems();
}
}
private Rectangle GetStarBounds(BetterListViewItemBounds bounds)
{
Rectangle rectInner = bounds.BoundsInner;
int widthImage = this.imageStarNormal.Width;
int heightImage = this.imageStarNormal.Height;
return (new Rectangle(
rectInner.Width - widthImage,
rectInner.Top + ((rectInner.Height - heightImage) >> 1),
widthImage,
heightImage));
}
}

Categories