2

我有一个使用 FlowLayoutPanel 的 WinForm 应用程序,它显示具有多个页面的 .TIFF 文件。FlowLayoutPanel 在 ThumbNails 视图中显示所有页面。

我已经实现了适用于单个项目的拖放逻辑。现在,我想更改它以允许用户选择多个缩略图(使用 CTRL 或 Shift 键)并将拖放到不同的位置。

//** Logic after each thumbnail is generated:
PictureBox thumb = new myProject.utility.PictureBox(pageNum);

thumb.Image = doc.getThumb(pageNum);  //since we pre loaded, we won't stall the gui thread.
thumb.Click += new System.EventHandler(
    (thumbSend, thumbEvent) =>
    {
        highLightThumb(thumb.getPage());
    }
);
thumb.DoubleClick += new System.EventHandler(
    (thumbSend, thumbEvent) =>
    {
        selectedDoc = thumb.getPage();
        me.Visible = false;
    }
);
thumbFlow.Controls.Add(thumb);
if (selectedDoc == pageNum)
    highLightThumb(pageNum);



//** Highlight Methods
private void highLightThumb(int page)
{
   //clear highlight
    foreach (Control c in thumbFlow.Controls)
    {
        if (c is PictureBox)
        {
            ((PictureBox)c).highlight = false;
         }
    }

    //apply highlight
    foreach (Control c in thumbFlow.Controls)
    {
        if (c is PictureBox)
        {
            PictureBox thumbFrame = (PictureBox)c;
            if (page == thumbFrame.getPage())
                thumbFrame.highlight = true;
        }
    }

}

下面是现有的拖放逻辑。

//**********************//
//** Drag/Drop Events **//
//**********************//
private void thumbFlow_DragDrop(object sender, DragEventArgs e)
{
    PictureBox data = (PictureBox)e.Data.GetData(typeof(PictureBox));
    FlowLayoutPanel _destination = (FlowLayoutPanel)sender;

    Point p = _destination.PointToClient(new Point(e.X, e.Y));
    var item = _destination.GetChildAtPoint(p);
    if (item == null)
    {
        p.Y = p.Y - 10;
        item = _destination.GetChildAtPoint(p);
    }
    int index = _destination.Controls.GetChildIndex(item, false);
    if (index < 0)
        return;

    _destination.Controls.SetChildIndex(data, index);
    _destination.Invalidate();

}

private void thumbFlow_DragEnter(object sender, DragEventArgs e)
{
    //apply/clear highlight
    foreach (Control c in thumbFlow.Controls)
    {
        if (c is PictureBox)
        {
            PictureBox thumbFrame = (PictureBox)c;
            if (thumbFrame == ActiveControl)
            {
                thumbFrame.highlight = true;
            }
            else
            {
                ((PictureBox)c).highlight = false;
            }
        }
    }
    e.Effect = DragDropEffects.Move;
    if (dragDropOccurred == false)
    {
        dragDropOccurred = true;
    }
}

//** Scroll when user drags above or below the window object  **//
private void thumbFlow_DragLeave(object sender, EventArgs e)
{
    int BegY_ThumbFlow = this.thumbFlow.FindForm().PointToClient(this.thumbFlow.Parent.PointToScreen(this.thumbFlow.Location)).Y;
    int thumbFlowBound_Y = this.thumbFlow.Height + BegY_ThumbFlow;
    int mouseY = this.thumbFlow.FindForm().PointToClient(MousePosition).Y;

    while (mouseY >= thumbFlowBound_Y)
    {
        thumbFlow.VerticalScroll.Value = thumbFlow.VerticalScroll.Value + DRAG_DROP_SCROLL_AMT;
        mouseY = thumbFlow.FindForm().PointToClient(MousePosition).Y;
        thumbFlow.Refresh();
    }

    while (mouseY <= BegY_ThumbFlow)
    {
        thumbFlow.VerticalScroll.Value = thumbFlow.VerticalScroll.Value - DRAG_DROP_SCROLL_AMT;
        mouseY = thumbFlow.FindForm().PointToClient(MousePosition).Y;
        thumbFlow.Refresh();
    }

}

我正在查看的一个选项是更改 highLightThumb 方法以检查是否选择了 CTRL 或 Shift 键并且不禁用高光

 if (Control.ModifierKeys != Keys.Control)
 //**
 if (Control.ModifierKeys != Keys.Shift)

然后更改 DragDrop DragEnter 例程。任何帮助将不胜感激。

4

1 回答 1

2

这是我最终做的..

生成缩略图后:

PictureBox thumb = new util.PictureBox(pageNum);
thumb.Image = doc.getThumb(pageNum);  //since we pre loaded, we won't stall the gui thread.
thumb.SizeMode = PictureBoxSizeMode.CenterImage;
thumb.BorderStyle = BorderStyle.FixedSingle;
thumb.Click += new System.EventHandler(
    (thumbSend, thumbEvent) =>
    {
        selectThumb(thumb);
    }
);
thumb.DoubleClick += new System.EventHandler(
    (thumbSend, thumbEvent) =>
    {
        selectedDoc = thumb.getPage();
        me.Visible = false;
    }
);
thumbFlow.Controls.Add(thumb);
if (selectedDoc == pageNum)
    selectThumb(thumb);

现在是缩略图选择代码。
在 Picturebox 逻辑中,我现在放置了一个名为 pageIndex 的变量。它用页码初始化。这样做的目的是因为稍后您将看到,当我旋转对象时,如果我更改 childindex 值,它似乎会立即发生,如果我拖动项目 2、3、4,它将跳过项目 3 并且只移动项目 2 和 4。所以稍后当我重新排列拇指时,我首先按 pageIndex 排序。

//*************************************//
//** Thumbnail Selection Processing  **//
//*************************************//
/// <summary>
/// Main Thumbnail selection area.  
///    If the Shift key is held down, look for a search between.  
///    If Ctrl key, do not clear selections as can select multiple.
/// </summary>
private void selectThumb(PictureBox _thumb)
{
    if (Control.ModifierKeys == Keys.Shift)
        if (SelectMultipleThumbs(_thumb.getPageIndex()))  //** if another thumb is selected, select all in between, then exit  **//
            return;

    if (Control.ModifierKeys != Keys.Control)
    {
        ClearAllSelections();
    }
    else
    {
        if (_thumb.IsSelected == true)
        {
            _thumb.IsSelected = false;
            return;
        }
    }

    _thumb.IsSelected = true;
}

/// <summary>
/// Check if there are other selected items.  If there is, select all between the start and end.
/// </summary>
private bool SelectMultipleThumbs(int _pageindex)
{
    //** Check if there are other objects that have been selected **/
    int? otherSelPageIndex = GetPageIndexOfThumbSelected(_pageindex);
    if (otherSelPageIndex != null)
    {
        ApplySelectionBetweenStartEndPageIndex(_pageindex, Convert.ToInt32(otherSelPageIndex));
        return true;
    }
    return false;
}

/// <summary>
/// Apply Selection if between start and end Pages
/// </summary>
private void ApplySelectionBetweenStartEndPageIndex(int _val1, int _val2)
{
    int startThumb = _val1;
    int endThumb = _val2;
    if (_val1 > _val2)
    {
        startThumb = _val2;
        endThumb = _val1;
    }

    foreach (PictureBox thumbFrame in thumbFlow.Controls.OfType<PictureBox>().OrderBy(si => si.pageIndex))
    {
        if (isBetween(thumbFrame.getPageIndex(), startThumb, endThumb))
            thumbFrame.IsSelected = true;
        else
            thumbFrame.IsSelected = false;
    }
}

/// <summary>
/// Clear All Highlight
/// </summary>
private void ClearAllSelections()
{
    foreach (PictureBox thumbFrame in thumbFlow.Controls.OfType<PictureBox>())
    {
        thumbFrame.IsSelected = false;
    }
}

/// <summary>
/// Check for any selected items prior
/// </summary>
private int? GetPageIndexOfThumbSelected(int _pageindex)
{
    foreach (PictureBox thumbFrame in thumbFlow.Controls.OfType<PictureBox>())
    {
        if (thumbFrame.IsSelected &&
            _pageindex != thumbFrame.getPageIndex())
        {
            return thumbFrame.getPageIndex();
        }
    }
    return null;
}

现在到拖放的处理。

private void thumbFlow_DragDrop(object sender, DragEventArgs e)
{
    FlowLayoutPanel _destination = (FlowLayoutPanel)sender;

    Point p = _destination.PointToClient(new Point(e.X, e.Y));
    var item = _destination.GetChildAtPoint(p);
    if (item == null)
    {
        p.Y = p.Y - 10;
        item = _destination.GetChildAtPoint(p);
    }
    int dropIndexValue = _destination.Controls.GetChildIndex(item, false);
    if (dropIndexValue < 0)
        return;

    //**************************************************//
    //**  Process multiple Select Drag / Drop   
    //**    If Drag From > Drag To, move after.
    //**    If Drag From < Drag To, move before.
    //**************************************************//

    //** First .. Find all items that are selected **//
    Boolean WasDragUp = false;
    int? firstDragIndexValue = null;
    int newIndexVal = dropIndexValue;
    foreach (PictureBox thumbFrame in thumbFlow.Controls.OfType<PictureBox>().Where(selVal => selVal.IsSelected))
    {
        if (firstDragIndexValue == null)
        {
            firstDragIndexValue = _destination.Controls.GetChildIndex(thumbFrame, false);
            if (firstDragIndexValue > dropIndexValue)
                WasDragUp = true;
        }
        thumbFrame.pageIndex = newIndexVal;
        newIndexVal++;
    }

    //** Second .. Find all items that are NOT selected **//
    if (WasDragUp)
    {
        newIndexVal = 0;
        foreach (PictureBox thumbFrame in thumbFlow.Controls.OfType<PictureBox>().Where(selVal => !selVal.IsSelected))
        {
            if (_destination.Controls.GetChildIndex(thumbFrame, false) == dropIndexValue)
                if (newIndexVal <= dropIndexValue)
                    newIndexVal = dropIndexValue + getThumbSelectedCnt();
            thumbFrame.pageIndex = newIndexVal;
            newIndexVal++;
        }
    }
    else
    {
        newIndexVal = 0;
        foreach (PictureBox thumbFrame in thumbFlow.Controls.OfType<PictureBox>().Where(selVal => !selVal.IsSelected))
        {
            thumbFrame.pageIndex = newIndexVal;
            if (_destination.Controls.GetChildIndex(thumbFrame, false) == dropIndexValue)
            {
                newIndexVal = dropIndexValue + getThumbSelectedCnt();
            }
            newIndexVal++;
        }
    }

    //** Third .. Set the Child Index value  **//
    newIndexVal = 0;
    foreach (PictureBox thumbFrame in thumbFlow.Controls.OfType<PictureBox>().OrderBy(si => si.pageIndex))
    {
        thumbFrame.pageIndex = newIndexVal;
        _destination.Controls.SetChildIndex(thumbFrame, thumbFrame.pageIndex);
        thumbFrame.IsSelected = false;
        newIndexVal++;
    }

    //** Finally, rebuild the screen  **//
    _destination.Invalidate();

}

private void thumbFlow_DragEnter(object sender, DragEventArgs e)
{
    //apply/clear highlight
    foreach (PictureBox thumbFrame in thumbFlow.Controls.OfType<PictureBox>())
    {
        if (thumbFrame == ActiveControl)
        {
            thumbFrame.IsSelected = true;
        }
    }

    e.Effect = DragDropEffects.Move;
    if (dragDropOccurred == false)
    {
        dragDropOccurred = true;
    }
}

/// <summary>
/// Scroll when user drags above or below the window object.
/// </summary>
private void thumbFlow_DragLeave(object sender, EventArgs e)
{
    int BegY_ThumbFlow = this.thumbFlow.FindForm().PointToClient(this.thumbFlow.Parent.PointToScreen(this.thumbFlow.Location)).Y;
    int thumbFlowBound_Y = this.thumbFlow.Height + BegY_ThumbFlow;
    int mouseY = this.thumbFlow.FindForm().PointToClient(MousePosition).Y;

    while (mouseY >= thumbFlowBound_Y)
    {
        thumbFlow.VerticalScroll.Value = thumbFlow.VerticalScroll.Value + DRAG_DROP_SCROLL_AMT;
        mouseY = thumbFlow.FindForm().PointToClient(MousePosition).Y;
        thumbFlow.Refresh();
    }

    while (mouseY <= BegY_ThumbFlow)
    {
        thumbFlow.VerticalScroll.Value = thumbFlow.VerticalScroll.Value - DRAG_DROP_SCROLL_AMT;
        mouseY = thumbFlow.FindForm().PointToClient(MousePosition).Y;
        thumbFlow.Refresh();
    }

}

更新文件

我会把我的代码放在这里,但它确实更具体地针对每个人的计划。我基本上重建了文件并保存了它。

于 2012-10-02T20:25:09.383 回答